Diff between a446569b866591ba071564e9222eef6453edfc05 and 125a2e237e7c2b688f1cf26e1a3b3c7279ff5b06

Changed Files

File Additions Deletions Status
profiles/audio/a2dp.c +22 -0 modified

Full Patch

diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index 58e1534..cf00400 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -104,6 +104,7 @@ struct a2dp_setup {
 	gboolean reconfigure;
 	gboolean start;
 	GSList *cb;
+	GIOChannel *io;
 	int ref;
 };
 
@@ -158,6 +159,11 @@ static void setup_free(struct a2dp_setup *s)
 {
 	DBG("%p", s);
 
+	if (s->io) {
+		g_io_channel_shutdown(s->io, TRUE, NULL);
+		g_io_channel_unref(s->io);
+	}
+
 	setups = g_slist_remove(setups, s);
 	if (s->session)
 		avdtp_unref(s->session);
@@ -1475,6 +1481,7 @@ static void transport_cb(GIOChannel *io, GError *err, gpointer user_data)
 
 	if (err) {
 		error("%s", err->message);
+		if (err)
 		goto drop;
 	}
 
@@ -1493,6 +1500,9 @@ static void transport_cb(GIOChannel *io, GError *err, gpointer user_data)
 
 	g_io_channel_set_close_on_unref(io, FALSE);
 
+	g_io_channel_unref(setup->io);
+	setup->io = NULL;
+
 	setup_unref(setup);
 
 	return;
@@ -1537,12 +1547,24 @@ static void confirm_cb(GIOChannel *io, gpointer data)
 		if (!setup || !setup->stream)
 			goto drop;
 
+		if (setup->io) {
+			error("transport channel already exists");
+			goto drop;
+		}
+
 		if (!bt_io_accept(io, transport_cb, setup, NULL, &err)) {
 			error("bt_io_accept: %s", err->message);
 			g_error_free(err);
 			goto drop;
 		}
 
+		/*
+		 * Reference the channel so it can be shutdown properly
+		 * stopping bt_io_accept from calling the callback with invalid
+		 * setup pointer.
+		 */
+		setup->io = g_io_channel_ref(io);
+
 		return;
 	}