Hi Marijn, On Sun, Oct 25, 2020 at 9:27 AM Marijn Suijten <marijns95@xxxxxxxxx> wrote: > > 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); Afaik this was done on purpose since we only need a weak reference as taking a reference would prevent the session to be disconnected when there is no setup in place, so I pretty sure this will cause regressions, instead we should probably add a reference when reconfiguring is in place and have a grace period for switching to another codec. > 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 -- Luiz Augusto von Dentz