[PATCH BlueZ] audio/a2dp: a2dp_channel should have a refcount on avdtp session

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



a2dp_channel keeps a reference to an avdtp session without incrementing
its refcount.  Not only does this appear wrong, it causes unexpected
disconnections when the remote SEP responds with rejections.

During testing with an audio application disconnections are observed
when a codec config change through MediaEndpoint1.SetConfiguration
fails.  As soon as BlueZ receives this failure from the peer the
corresponding a2dp_setup object is cleaned up which holds the last
refcount to an avdtp session, in turn starting the disconnect process.
An eventual open sink/source and transport have already closed by that
time and released their refcounts.

Adding refcounting semantics around a2dp_channel resolves the
disconnections and allows future calls on MediaEndpoint1 to safely
access the sesion stored within this channel.
---
 profiles/audio/a2dp.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
index cc4866b5b..0eac0135f 100644
--- a/profiles/audio/a2dp.c
+++ b/profiles/audio/a2dp.c
@@ -1507,6 +1507,9 @@ static void channel_free(void *data)
 
 	avdtp_remove_state_cb(chan->state_id);
 
+	if (chan->session)
+		avdtp_unref(chan->session);
+
 	queue_destroy(chan->seps, remove_remote_sep);
 	free(chan->last_used);
 	g_free(chan);
@@ -2065,7 +2068,7 @@ static void avdtp_state_cb(struct btd_device *dev, struct avdtp *session,
 		break;
 	case AVDTP_SESSION_STATE_CONNECTED:
 		if (!chan->session)
-			chan->session = session;
+			chan->session = avdtp_ref(session);
 		load_remote_seps(chan);
 		break;
 	}
@@ -2145,6 +2148,7 @@ found:
 		channel_remove(chan);
 		return NULL;
 	}
+	avdtp_ref(chan->session);
 
 	return avdtp_ref(chan->session);
 }
@@ -2165,6 +2169,7 @@ static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
 			error("Unable to create AVDTP session");
 			goto fail;
 		}
+		avdtp_ref(chan->session);
 	}
 
 	g_io_channel_unref(chan->io);
-- 
2.29.1

Marijn Suijten



[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux