diff mbox series

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

Message ID 20201025162730.47247-1-marijns95@gmail.com (mailing list archive)
State New, archived
Headers show
Series [BlueZ] audio/a2dp: a2dp_channel should have a refcount on avdtp session | expand

Commit Message

Marijn Suijten Oct. 25, 2020, 4:27 p.m. UTC
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(-)

Comments

bluez.test.bot@gmail.com Oct. 25, 2020, 4:44 p.m. UTC | #1
This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=370053

---Test result---

##############################
Test: CheckPatch - PASS

##############################
Test: CheckGitLint - PASS

##############################
Test: CheckBuild - PASS

##############################
Test: MakeCheck - PASS



---
Regards,
Linux Bluetooth
Luiz Augusto von Dentz Oct. 26, 2020, 8:15 p.m. UTC | #2
Hi Marijn,

On Sun, Oct 25, 2020 at 9:27 AM Marijn Suijten <marijns95@gmail.com> 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
Marijn Suijten Oct. 26, 2020, 8:22 p.m. UTC | #3
Hi Luiz,

On Mon, 26 Oct 2020 at 21:15, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
>
> Hi Marijn,
>
> On Sun, Oct 25, 2020 at 9:27 AM Marijn Suijten <marijns95@gmail.com> 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.

Allright, so it's either an in-progress setup or ongoing transport
keeping the session alive, nothing else?  I guess this is as simple as
setting a higher dc_timeout when calling set_disconnect_timer in
avdtp_unref?

>
> >                 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

Marijn Suijten
Luiz Augusto von Dentz Oct. 26, 2020, 8:38 p.m. UTC | #4
Hi Marijn,

On Mon, Oct 26, 2020 at 1:22 PM Marijn Suijten <marijns95@gmail.com> wrote:
>
> Hi Luiz,
>
> On Mon, 26 Oct 2020 at 21:15, Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
> >
> > Hi Marijn,
> >
> > On Sun, Oct 25, 2020 at 9:27 AM Marijn Suijten <marijns95@gmail.com> 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.
>
> Allright, so it's either an in-progress setup or ongoing transport
> keeping the session alive, nothing else?  I guess this is as simple as
> setting a higher dc_timeout when calling set_disconnect_timer in
> avdtp_unref?

Yep, actually now that you mentioned the dc_timeout that should have
prevented us to disconnect immediately when reconfiguring as we should
have been in AVDTP_SESSION_STATE_CONNECTED state but I think the
problem is that we use avdtp_close to reconfigure which does set the
dc_timeout to 0 since that is normally used for cleaning up the
session, so I think we may need to restore the dc_timeout to
DISCONNECT_TIMEOUT if we attempt to set a configuration:

diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
index ae93fb26f..97b4d1b44 100644
--- a/profiles/audio/avdtp.c
+++ b/profiles/audio/avdtp.c
@@ -3498,6 +3498,7 @@ int avdtp_set_configuration(struct avdtp *session,
                session->streams = g_slist_append(session->streams, new_stream);
                if (stream)
                        *stream = new_stream;
+               session->dc_timeout = DISCONNECT_TIMEOUT;
        }

        g_free(req);


> >
> > >                 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
>
> Marijn Suijten
Marijn Suijten Oct. 26, 2020, 9:37 p.m. UTC | #5
Hi Luiz,

On Mon, 26 Oct 2020 at 21:39, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
>
> Hi Marijn,
>
> On Mon, Oct 26, 2020 at 1:22 PM Marijn Suijten <marijns95@gmail.com> wrote:
> >
> > Hi Luiz,
> >
> > On Mon, 26 Oct 2020 at 21:15, Luiz Augusto von Dentz
> > <luiz.dentz@gmail.com> wrote:
> > >
> > > Hi Marijn,
> > >
> > > On Sun, Oct 25, 2020 at 9:27 AM Marijn Suijten <marijns95@gmail.com> 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.
> >
> > Allright, so it's either an in-progress setup or ongoing transport
> > keeping the session alive, nothing else?  I guess this is as simple as
> > setting a higher dc_timeout when calling set_disconnect_timer in
> > avdtp_unref?
>
> Yep, actually now that you mentioned the dc_timeout that should have
> prevented us to disconnect immediately when reconfiguring as we should
> have been in AVDTP_SESSION_STATE_CONNECTED state but I think the
> problem is that we use avdtp_close to reconfigure which does set the
> dc_timeout to 0

Yep a2dp_reconfig calls that functionand sets it to 0.

> since that is normally used for cleaning up the
> session, so I think we may need to restore the dc_timeout to
> DISCONNECT_TIMEOUT if we attempt to set a configuration:

My thinking as well, assuming DISCONNECT_TIMEOUT is enough (1s).

> diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
> index ae93fb26f..97b4d1b44 100644
> --- a/profiles/audio/avdtp.c
> +++ b/profiles/audio/avdtp.c
> @@ -3498,6 +3498,7 @@ int avdtp_set_configuration(struct avdtp *session,
>                 session->streams = g_slist_append(session->streams, new_stream);
>                 if (stream)
>                         *stream = new_stream;
> +               session->dc_timeout = DISCONNECT_TIMEOUT;
>         }
>
>         g_free(req);
>
>

Thanks, works like a charm!

    profiles/audio/avdtp.c:avdtp_unref() 0x5565f10db6f0: ref=1
    profiles/audio/avdtp.c:avdtp_set_configuration() 0x5565f10db6f0:
int_seid=8, acp_seid=1
    profiles/audio/avdtp.c:session_cb()
    profiles/audio/avdtp.c:avdtp_parse_rej() SET_CONFIGURATION request
rejected: Configuration not supported (41)
    profiles/audio/a2dp.c:setconf_cfm() Source 0x5565f10fc620:
Set_Configuration_Cfm
    profiles/audio/a2dp.c:setup_ref() 0x5565f110d540: ref=2
    profiles/audio/a2dp.c:setup_unref() 0x5565f110d540: ref=1
    profiles/audio/a2dp.c:setup_unref() 0x5565f110d540: ref=0
    profiles/audio/a2dp.c:setup_free() 0x5565f110d540
    profiles/audio/avdtp.c:avdtp_unref() 0x5565f10db6f0: ref=0
    profiles/audio/avdtp.c:avdtp_ref() 0x5565f10db6f0: ref=1
    profiles/audio/avdtp.c:set_disconnect_timer() timeout 1
    profiles/audio/avdtp.c:avdtp_ref() 0x5565f10db6f0: ref=2
    profiles/audio/avdtp.c:avdtp_unref() 0x5565f10db6f0: ref=1
    profiles/audio/a2dp.c:setup_ref() 0x5565f110d540: ref=1
    profiles/audio/avdtp.c:avdtp_set_configuration() 0x5565f10db6f0:
int_seid=8, acp_seid=7
    profiles/audio/avdtp.c:session_cb()
    profiles/audio/avdtp.c:avdtp_parse_resp() SET_CONFIGURATION
request succeeded
    profiles/audio/a2dp.c:setconf_cfm() Source 0x5565f10fc620:
Set_Configuration_Cfm

Since you suggested this change I guess it's up to you to write a
commit around it and apply it or submit it for additional review, or
should I do it and combine it with the original message for a v2?

> > >
> > > >                 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
> >
> > Marijn Suijten
>
>
>
> --
> Luiz Augusto von Dentz

Marijn Suijten
Luiz Augusto von Dentz Oct. 26, 2020, 11:48 p.m. UTC | #6
Hi Marijn,

On Mon, Oct 26, 2020 at 2:37 PM Marijn Suijten <marijns95@gmail.com> wrote:
>
> Hi Luiz,
>
> On Mon, 26 Oct 2020 at 21:39, Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
> >
> > Hi Marijn,
> >
> > On Mon, Oct 26, 2020 at 1:22 PM Marijn Suijten <marijns95@gmail.com> wrote:
> > >
> > > Hi Luiz,
> > >
> > > On Mon, 26 Oct 2020 at 21:15, Luiz Augusto von Dentz
> > > <luiz.dentz@gmail.com> wrote:
> > > >
> > > > Hi Marijn,
> > > >
> > > > On Sun, Oct 25, 2020 at 9:27 AM Marijn Suijten <marijns95@gmail.com> 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.
> > >
> > > Allright, so it's either an in-progress setup or ongoing transport
> > > keeping the session alive, nothing else?  I guess this is as simple as
> > > setting a higher dc_timeout when calling set_disconnect_timer in
> > > avdtp_unref?
> >
> > Yep, actually now that you mentioned the dc_timeout that should have
> > prevented us to disconnect immediately when reconfiguring as we should
> > have been in AVDTP_SESSION_STATE_CONNECTED state but I think the
> > problem is that we use avdtp_close to reconfigure which does set the
> > dc_timeout to 0
>
> Yep a2dp_reconfig calls that functionand sets it to 0.
>
> > since that is normally used for cleaning up the
> > session, so I think we may need to restore the dc_timeout to
> > DISCONNECT_TIMEOUT if we attempt to set a configuration:
>
> My thinking as well, assuming DISCONNECT_TIMEOUT is enough (1s).
>
> > diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c
> > index ae93fb26f..97b4d1b44 100644
> > --- a/profiles/audio/avdtp.c
> > +++ b/profiles/audio/avdtp.c
> > @@ -3498,6 +3498,7 @@ int avdtp_set_configuration(struct avdtp *session,
> >                 session->streams = g_slist_append(session->streams, new_stream);
> >                 if (stream)
> >                         *stream = new_stream;
> > +               session->dc_timeout = DISCONNECT_TIMEOUT;
> >         }
> >
> >         g_free(req);
> >
> >
>
> Thanks, works like a charm!
>
>     profiles/audio/avdtp.c:avdtp_unref() 0x5565f10db6f0: ref=1
>     profiles/audio/avdtp.c:avdtp_set_configuration() 0x5565f10db6f0:
> int_seid=8, acp_seid=1
>     profiles/audio/avdtp.c:session_cb()
>     profiles/audio/avdtp.c:avdtp_parse_rej() SET_CONFIGURATION request
> rejected: Configuration not supported (41)
>     profiles/audio/a2dp.c:setconf_cfm() Source 0x5565f10fc620:
> Set_Configuration_Cfm
>     profiles/audio/a2dp.c:setup_ref() 0x5565f110d540: ref=2
>     profiles/audio/a2dp.c:setup_unref() 0x5565f110d540: ref=1
>     profiles/audio/a2dp.c:setup_unref() 0x5565f110d540: ref=0
>     profiles/audio/a2dp.c:setup_free() 0x5565f110d540
>     profiles/audio/avdtp.c:avdtp_unref() 0x5565f10db6f0: ref=0
>     profiles/audio/avdtp.c:avdtp_ref() 0x5565f10db6f0: ref=1
>     profiles/audio/avdtp.c:set_disconnect_timer() timeout 1
>     profiles/audio/avdtp.c:avdtp_ref() 0x5565f10db6f0: ref=2
>     profiles/audio/avdtp.c:avdtp_unref() 0x5565f10db6f0: ref=1
>     profiles/audio/a2dp.c:setup_ref() 0x5565f110d540: ref=1
>     profiles/audio/avdtp.c:avdtp_set_configuration() 0x5565f10db6f0:
> int_seid=8, acp_seid=7
>     profiles/audio/avdtp.c:session_cb()
>     profiles/audio/avdtp.c:avdtp_parse_resp() SET_CONFIGURATION
> request succeeded
>     profiles/audio/a2dp.c:setconf_cfm() Source 0x5565f10fc620:
> Set_Configuration_Cfm
>
> Since you suggested this change I guess it's up to you to write a
> commit around it and apply it or submit it for additional review, or
> should I do it and combine it with the original message for a v2?

I went ahead and applied it myself, thanks for confirming it works properly.

> > > >
> > > > >                 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
> > >
> > > Marijn Suijten
> >
> >
> >
> > --
> > Luiz Augusto von Dentz
>
> Marijn Suijten
diff mbox series

Patch

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);