* [PATCH] avdtp: Fix crash on connection lost
@ 2012-10-16 12:37 Szymon Janc
2012-10-16 17:34 ` Luiz Augusto von Dentz
0 siblings, 1 reply; 7+ messages in thread
From: Szymon Janc @ 2012-10-16 12:37 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
This fix avdtp session reference counting. avdtp_unref has a special
case when ref==1 and due to nested calls session could be free in
consecutive call resulting in accesing already freed memory.
Instead of having extra free lock keep extra local reference. This also
make avdtp_unref easier to undertand as there is no double ref
decrement inside one unref call.
avdtp_unref will set session state to disconnected when reference count
drops to 1 so there is no need to explicite set it in connection_lost.
bluetoothd[29474]: audio/avdtp.c:avdtp_ref() 0x555555856aa0: ref=2
bluetoothd[29474]: audio/source.c:source_connect() stream creation in progress
bluetoothd[29474]: src/mgmt.c:mgmt_event() cond 1
bluetoothd[29474]: src/mgmt.c:mgmt_event() Received 31 bytes from management socket
bluetoothd[29474]: src/mgmt.c:mgmt_device_connected() hci0 device 84:00:D2:DB:F7:8C connected eir_len 12
bluetoothd[29474]: src/adapter.c:adapter_get_device() 84:00:D2:DB:F7:8C
bluetoothd[29474]: src/mgmt.c:mgmt_event() cond 1
bluetoothd[29474]: src/mgmt.c:mgmt_event() Received 14 bytes from management socket
bluetoothd[29474]: src/mgmt.c:mgmt_auth_failed() hci0 auth failed status 6
bluetoothd[29474]: src/device.c:device_bonding_complete() bonding (nil) status 0x06
bluetoothd[29474]: connect error: Invalid exchange (52)
bluetoothd[29474]: audio/avdtp.c:connection_lost() Disconnected from 84:00:D2:DB:F7:8C
bluetoothd[29474]: audio/avdtp.c:avdtp_unref() 0x555555856aa0: ref=1
bluetoothd[29474]: audio/avdtp.c:avdtp_unref() 0x555555856aa0: ref=0
bluetoothd[29474]: audio/avdtp.c:avdtp_unref() 0x555555856aa0: freeing session and removing from list
bluetoothd[29474]: audio/avdtp.c:avdtp_unref() 0x555555856aa0: freeing session and removing from list
Program received signal SIGSEGV, Segmentation fault.
avdtp_unref (session=0x555555856aa0) at audio/avdtp.c:1239
1239 server->sessions = g_slist_remove(server->sessions, session);
---
audio/avdtp.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/audio/avdtp.c b/audio/avdtp.c
index bd91cb6..4109be9 100644
--- a/audio/avdtp.c
+++ b/audio/avdtp.c
@@ -388,7 +388,6 @@ struct avdtp_stream {
struct avdtp {
int ref;
- int free_lock;
uint16_t version;
@@ -1158,14 +1157,14 @@ static void connection_lost(struct avdtp *session, int err)
if (err != EACCES)
avdtp_cancel_authorization(session);
- session->free_lock = 1;
+ avdtp_ref(session);
finalize_discovery(session, err);
g_slist_foreach(session->streams, (GFunc) release_stream, session);
session->streams = NULL;
- session->free_lock = 0;
+ avdtp_unref(session);
if (session->io) {
g_io_channel_shutdown(session->io, FALSE, NULL);
@@ -1173,8 +1172,6 @@ static void connection_lost(struct avdtp *session, int err)
session->io = NULL;
}
- avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);
-
if (session->io_id) {
g_source_remove(session->io_id);
session->io_id = 0;
@@ -1221,9 +1218,6 @@ void avdtp_unref(struct avdtp *session)
if (session->io)
set_disconnect_timer(session);
- else if (!session->free_lock) /* Drop the local ref if we
- aren't connected */
- session->ref--;
}
if (session->ref > 0)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] avdtp: Fix crash on connection lost
2012-10-16 12:37 [PATCH] avdtp: Fix crash on connection lost Szymon Janc
@ 2012-10-16 17:34 ` Luiz Augusto von Dentz
2012-10-16 17:43 ` Luiz Augusto von Dentz
2012-10-17 7:28 ` Szymon Janc
0 siblings, 2 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2012-10-16 17:34 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
Hi Szymon,
On Tue, Oct 16, 2012 at 2:37 PM, Szymon Janc <szymon.janc@tieto.com> wrote:
> This fix avdtp session reference counting. avdtp_unref has a special
> case when ref==1 and due to nested calls session could be free in
> consecutive call resulting in accesing already freed memory.
>
> Instead of having extra free lock keep extra local reference. This also
> make avdtp_unref easier to undertand as there is no double ref
> decrement inside one unref call.
>
> avdtp_unref will set session state to disconnected when reference count
> drops to 1 so there is no need to explicite set it in connection_lost.
>
> bluetoothd[29474]: audio/avdtp.c:avdtp_ref() 0x555555856aa0: ref=2
> bluetoothd[29474]: audio/source.c:source_connect() stream creation in progress
> bluetoothd[29474]: src/mgmt.c:mgmt_event() cond 1
> bluetoothd[29474]: src/mgmt.c:mgmt_event() Received 31 bytes from management socket
> bluetoothd[29474]: src/mgmt.c:mgmt_device_connected() hci0 device 84:00:D2:DB:F7:8C connected eir_len 12
> bluetoothd[29474]: src/adapter.c:adapter_get_device() 84:00:D2:DB:F7:8C
> bluetoothd[29474]: src/mgmt.c:mgmt_event() cond 1
> bluetoothd[29474]: src/mgmt.c:mgmt_event() Received 14 bytes from management socket
> bluetoothd[29474]: src/mgmt.c:mgmt_auth_failed() hci0 auth failed status 6
> bluetoothd[29474]: src/device.c:device_bonding_complete() bonding (nil) status 0x06
> bluetoothd[29474]: connect error: Invalid exchange (52)
> bluetoothd[29474]: audio/avdtp.c:connection_lost() Disconnected from 84:00:D2:DB:F7:8C
> bluetoothd[29474]: audio/avdtp.c:avdtp_unref() 0x555555856aa0: ref=1
> bluetoothd[29474]: audio/avdtp.c:avdtp_unref() 0x555555856aa0: ref=0
> bluetoothd[29474]: audio/avdtp.c:avdtp_unref() 0x555555856aa0: freeing session and removing from list
> bluetoothd[29474]: audio/avdtp.c:avdtp_unref() 0x555555856aa0: freeing session and removing from list
>
> Program received signal SIGSEGV, Segmentation fault.
> avdtp_unref (session=0x555555856aa0) at audio/avdtp.c:1239
> 1239 server->sessions = g_slist_remove(server->sessions, session);
>
> ---
> audio/avdtp.c | 10 ++--------
> 1 file changed, 2 insertions(+), 8 deletions(-)
>
> diff --git a/audio/avdtp.c b/audio/avdtp.c
> index bd91cb6..4109be9 100644
> --- a/audio/avdtp.c
> +++ b/audio/avdtp.c
> @@ -388,7 +388,6 @@ struct avdtp_stream {
>
> struct avdtp {
> int ref;
> - int free_lock;
>
> uint16_t version;
>
> @@ -1158,14 +1157,14 @@ static void connection_lost(struct avdtp *session, int err)
> if (err != EACCES)
> avdtp_cancel_authorization(session);
>
> - session->free_lock = 1;
> + avdtp_ref(session);
>
> finalize_discovery(session, err);
>
> g_slist_foreach(session->streams, (GFunc) release_stream, session);
> session->streams = NULL;
>
> - session->free_lock = 0;
> + avdtp_unref(session);
>
> if (session->io) {
> g_io_channel_shutdown(session->io, FALSE, NULL);
> @@ -1173,8 +1172,6 @@ static void connection_lost(struct avdtp *session, int err)
> session->io = NULL;
> }
>
> - avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);
This is actually the one that we need in case we got disconnect by
remote after discovery completes. avctp.c has a similar structure to
handler such states, but without the refcounting all is much simpler.
> if (session->io_id) {
> g_source_remove(session->io_id);
> session->io_id = 0;
> @@ -1221,9 +1218,6 @@ void avdtp_unref(struct avdtp *session)
>
> if (session->io)
> set_disconnect_timer(session);
> - else if (!session->free_lock) /* Drop the local ref if we
> - aren't connected */
> - session->ref--;
> }
>
> if (session->ref > 0)
> --
> 1.7.9.5
We should probably get rid of the free_lock as well.
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] avdtp: Fix crash on connection lost
2012-10-16 17:34 ` Luiz Augusto von Dentz
@ 2012-10-16 17:43 ` Luiz Augusto von Dentz
2012-10-17 7:28 ` Szymon Janc
1 sibling, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2012-10-16 17:43 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
Hi again,
On Tue, Oct 16, 2012 at 7:34 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> Hi Szymon,
>
> On Tue, Oct 16, 2012 at 2:37 PM, Szymon Janc <szymon.janc@tieto.com> wrote:
>> This fix avdtp session reference counting. avdtp_unref has a special
>> case when ref==1 and due to nested calls session could be free in
>> consecutive call resulting in accesing already freed memory.
>>
>> Instead of having extra free lock keep extra local reference. This also
>> make avdtp_unref easier to undertand as there is no double ref
>> decrement inside one unref call.
>>
>> avdtp_unref will set session state to disconnected when reference count
>> drops to 1 so there is no need to explicite set it in connection_lost.
>>
>> bluetoothd[29474]: audio/avdtp.c:avdtp_ref() 0x555555856aa0: ref=2
>> bluetoothd[29474]: audio/source.c:source_connect() stream creation in progress
>> bluetoothd[29474]: src/mgmt.c:mgmt_event() cond 1
>> bluetoothd[29474]: src/mgmt.c:mgmt_event() Received 31 bytes from management socket
>> bluetoothd[29474]: src/mgmt.c:mgmt_device_connected() hci0 device 84:00:D2:DB:F7:8C connected eir_len 12
>> bluetoothd[29474]: src/adapter.c:adapter_get_device() 84:00:D2:DB:F7:8C
>> bluetoothd[29474]: src/mgmt.c:mgmt_event() cond 1
>> bluetoothd[29474]: src/mgmt.c:mgmt_event() Received 14 bytes from management socket
>> bluetoothd[29474]: src/mgmt.c:mgmt_auth_failed() hci0 auth failed status 6
>> bluetoothd[29474]: src/device.c:device_bonding_complete() bonding (nil) status 0x06
>> bluetoothd[29474]: connect error: Invalid exchange (52)
>> bluetoothd[29474]: audio/avdtp.c:connection_lost() Disconnected from 84:00:D2:DB:F7:8C
>> bluetoothd[29474]: audio/avdtp.c:avdtp_unref() 0x555555856aa0: ref=1
>> bluetoothd[29474]: audio/avdtp.c:avdtp_unref() 0x555555856aa0: ref=0
>> bluetoothd[29474]: audio/avdtp.c:avdtp_unref() 0x555555856aa0: freeing session and removing from list
>> bluetoothd[29474]: audio/avdtp.c:avdtp_unref() 0x555555856aa0: freeing session and removing from list
>>
>> Program received signal SIGSEGV, Segmentation fault.
>> avdtp_unref (session=0x555555856aa0) at audio/avdtp.c:1239
>> 1239 server->sessions = g_slist_remove(server->sessions, session);
>>
>> ---
>> audio/avdtp.c | 10 ++--------
>> 1 file changed, 2 insertions(+), 8 deletions(-)
>>
>> diff --git a/audio/avdtp.c b/audio/avdtp.c
>> index bd91cb6..4109be9 100644
>> --- a/audio/avdtp.c
>> +++ b/audio/avdtp.c
>> @@ -388,7 +388,6 @@ struct avdtp_stream {
>>
>> struct avdtp {
>> int ref;
>> - int free_lock;
>>
>> uint16_t version;
>>
>> @@ -1158,14 +1157,14 @@ static void connection_lost(struct avdtp *session, int err)
>> if (err != EACCES)
>> avdtp_cancel_authorization(session);
>>
>> - session->free_lock = 1;
>> + avdtp_ref(session);
>>
>> finalize_discovery(session, err);
>>
>> g_slist_foreach(session->streams, (GFunc) release_stream, session);
>> session->streams = NULL;
>>
>> - session->free_lock = 0;
>> + avdtp_unref(session);
>>
>> if (session->io) {
>> g_io_channel_shutdown(session->io, FALSE, NULL);
>> @@ -1173,8 +1172,6 @@ static void connection_lost(struct avdtp *session, int err)
>> session->io = NULL;
>> }
>>
>> - avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);
>
> This is actually the one that we need in case we got disconnect by
> remote after discovery completes. avctp.c has a similar structure to
> handler such states, but without the refcounting all is much simpler.
>
>> if (session->io_id) {
>> g_source_remove(session->io_id);
>> session->io_id = 0;
>> @@ -1221,9 +1218,6 @@ void avdtp_unref(struct avdtp *session)
>>
>> if (session->io)
>> set_disconnect_timer(session);
>> - else if (!session->free_lock) /* Drop the local ref if we
>> - aren't connected */
>> - session->ref--;
>> }
>>
>> if (session->ref > 0)
>> --
>> 1.7.9.5
>
> We should probably get rid of the free_lock as well.
I just remembered the reason we have this strange refcount 1, it was
to keep the session up while the unix client/alsa client reconnects. I
think we can drop this altogether now that we don't support such bogus
clients, this also means dropping dc_timer and which should fix the
refcount for good.
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] avdtp: Fix crash on connection lost
2012-10-16 17:34 ` Luiz Augusto von Dentz
2012-10-16 17:43 ` Luiz Augusto von Dentz
@ 2012-10-17 7:28 ` Szymon Janc
2012-10-17 8:48 ` Luiz Augusto von Dentz
1 sibling, 1 reply; 7+ messages in thread
From: Szymon Janc @ 2012-10-17 7:28 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth@vger.kernel.org
On Tuesday 16 of October 2012 20:34:47 Luiz Augusto von Dentz wrote:
> Hi Szymon,
Hi Luiz,
> > if (session->io) {
> > g_io_channel_shutdown(session->io, FALSE, NULL);
> > @@ -1173,8 +1172,6 @@ static void connection_lost(struct avdtp *session, int err)
> > session->io = NULL;
> > }
> >
> > - avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);
>
> This is actually the one that we need in case we got disconnect by
> remote after discovery completes. avctp.c has a similar structure to
> handler such states, but without the refcounting all is much simpler.
OK
>
> > if (session->io_id) {
> > g_source_remove(session->io_id);
> > session->io_id = 0;
> > @@ -1221,9 +1218,6 @@ void avdtp_unref(struct avdtp *session)
> >
> > if (session->io)
> > set_disconnect_timer(session);
> > - else if (!session->free_lock) /* Drop the local ref if we
> > - aren't connected */
> > - session->ref--;
> > }
> >
> > if (session->ref > 0)
> > --
> > 1.7.9.5
>
> We should probably get rid of the free_lock as well.
Well, this is what this patch does, doesn't it?:)
--
BR
Szymon Janc
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] avdtp: Fix crash on connection lost
2012-10-17 7:28 ` Szymon Janc
@ 2012-10-17 8:48 ` Luiz Augusto von Dentz
2012-10-17 10:17 ` Szymon Janc
0 siblings, 1 reply; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2012-10-17 8:48 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 1770 bytes --]
Hi Szymon,
On Wed, Oct 17, 2012 at 9:28 AM, Szymon Janc <szymon.janc@tieto.com> wrote:
> On Tuesday 16 of October 2012 20:34:47 Luiz Augusto von Dentz wrote:
>> Hi Szymon,
>
> Hi Luiz,
>
>> > if (session->io) {
>> > g_io_channel_shutdown(session->io, FALSE, NULL);
>> > @@ -1173,8 +1172,6 @@ static void connection_lost(struct avdtp *session, int err)
>> > session->io = NULL;
>> > }
>> >
>> > - avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);
>>
>> This is actually the one that we need in case we got disconnect by
>> remote after discovery completes. avctp.c has a similar structure to
>> handler such states, but without the refcounting all is much simpler.
>
> OK
>
>>
>> > if (session->io_id) {
>> > g_source_remove(session->io_id);
>> > session->io_id = 0;
>> > @@ -1221,9 +1218,6 @@ void avdtp_unref(struct avdtp *session)
>> >
>> > if (session->io)
>> > set_disconnect_timer(session);
>> > - else if (!session->free_lock) /* Drop the local ref if we
>> > - aren't connected */
>> > - session->ref--;
>> > }
>> >
>> > if (session->ref > 0)
>> > --
>> > 1.7.9.5
>>
>> We should probably get rid of the free_lock as well.
>
> Well, this is what this patch does, doesn't it?:)
What about the attached patch, it should fix the references for good
by using the dc_timer when the reference drops to 0, I just need to
check if 1 second is enough to cover all cases including the ones
where the remote device connects but doesn't setup any stream, with
the devices I have 1 second seems enough.
--
Luiz Augusto von Dentz
[-- Attachment #2: 0001-AVDTP-Do-not-keep-a-internal-reference.patch --]
[-- Type: application/octet-stream, Size: 5527 bytes --]
From 39312cf09fac700505deb7babd129bec1b4e26dc Mon Sep 17 00:00:00 2001
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Date: Tue, 16 Oct 2012 23:09:53 +0300
Subject: [PATCH BlueZ] AVDTP: Do not keep a internal reference
Don't initialize reference with 1, instead always start disconnect timer
when reference drops to 0, so in case nobody reclaims the session it
automatically disconnect after 1 second and frees the memory.
---
audio/avdtp.c | 114 ++++++++++++++++++++++++++--------------------------------
1 file changed, 50 insertions(+), 64 deletions(-)
diff --git a/audio/avdtp.c b/audio/avdtp.c
index bd91cb6..e35b324 100644
--- a/audio/avdtp.c
+++ b/audio/avdtp.c
@@ -388,7 +388,6 @@ struct avdtp_stream {
struct avdtp {
int ref;
- int free_lock;
uint16_t version;
@@ -780,8 +779,9 @@ static void avdtp_set_state(struct avdtp *session,
}
}
-static void stream_free(struct avdtp_stream *stream)
+static void stream_free(void *data)
{
+ struct avdtp_stream *stream = data;
struct avdtp_remote_sep *rsep;
stream->lsep->info.inuse = 0;
@@ -1148,33 +1148,30 @@ static int avdtp_cancel_authorization(struct avdtp *session)
return 0;
}
-static void connection_lost(struct avdtp *session, int err)
+static void sep_free(gpointer data)
{
- char address[18];
-
- ba2str(&session->dst, address);
- DBG("Disconnected from %s", address);
+ struct avdtp_remote_sep *sep = data;
- if (err != EACCES)
- avdtp_cancel_authorization(session);
+ g_slist_free_full(sep->caps, g_free);
+ g_free(sep);
+}
- session->free_lock = 1;
+static void avdtp_free(struct avdtp *session)
+{
+ struct avdtp_server *server;
- finalize_discovery(session, err);
+ DBG("%p", session);
- g_slist_foreach(session->streams, (GFunc) release_stream, session);
- session->streams = NULL;
+ g_slist_free_full(session->streams, stream_free);
- session->free_lock = 0;
+ if (session->state != AVDTP_SESSION_STATE_DISCONNECTED)
+ avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);
if (session->io) {
g_io_channel_shutdown(session->io, FALSE, NULL);
g_io_channel_unref(session->io);
- session->io = NULL;
}
- avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);
-
if (session->io_id) {
g_source_remove(session->io_id);
session->io_id = 0;
@@ -1183,69 +1180,58 @@ static void connection_lost(struct avdtp *session, int err)
if (session->dc_timer)
remove_disconnect_timer(session);
- if (session->ref != 1)
- error("connection_lost: ref count not 1 after all callbacks");
- else
- avdtp_unref(session);
-}
+ avdtp_cancel_authorization(session);
-static void sep_free(gpointer data)
-{
- struct avdtp_remote_sep *sep = data;
+ server = session->server;
- g_slist_free_full(sep->caps, g_free);
- g_free(sep);
-}
+ server->sessions = g_slist_remove(server->sessions, session);
-void avdtp_unref(struct avdtp *session)
-{
- struct avdtp_server *server;
+ if (session->req)
+ pending_req_free(session->req);
- if (!session)
- return;
+ g_slist_free_full(session->seps, sep_free);
- session->ref--;
+ g_free(session->buf);
- DBG("%p: ref=%d", session, session->ref);
+ g_free(session);
+}
- if (session->ref == 1) {
- if (session->state == AVDTP_SESSION_STATE_CONNECTING &&
- session->io) {
- avdtp_cancel_authorization(session);
- g_io_channel_shutdown(session->io, TRUE, NULL);
- g_io_channel_unref(session->io);
- session->io = NULL;
- avdtp_set_state(session,
- AVDTP_SESSION_STATE_DISCONNECTED);
- }
+static void connection_lost(struct avdtp *session, int err)
+{
+ char address[18];
- if (session->io)
- set_disconnect_timer(session);
- else if (!session->free_lock) /* Drop the local ref if we
- aren't connected */
- session->ref--;
- }
+ ba2str(&session->dst, address);
+ DBG("Disconnected from %s", address);
- if (session->ref > 0)
+ if (err != EACCES)
+ avdtp_cancel_authorization(session);
+
+ if (session->ref == 0) {
+ avdtp_free(session);
return;
+ }
- server = session->server;
+ g_slist_foreach(session->streams, (GFunc) release_stream, session);
+ session->streams = NULL;
- DBG("%p: freeing session and removing from list", session);
+ finalize_discovery(session, err);
- if (session->dc_timer)
- remove_disconnect_timer(session);
+ avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED);
+}
- server->sessions = g_slist_remove(server->sessions, session);
+void avdtp_unref(struct avdtp *session)
+{
+ if (!session)
+ return;
- if (session->req)
- pending_req_free(session->req);
+ session->ref--;
- g_slist_free_full(session->seps, sep_free);
+ DBG("%p: ref=%d", session, session->ref);
- g_free(session->buf);
+ if (session->ref > 0)
+ return;
- g_free(session);
+ set_disconnect_timer(session);
}
struct avdtp *avdtp_ref(struct avdtp *session)
@@ -2231,7 +2217,7 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
goto failed;
}
- if (session->ref == 1 && !session->streams && !session->req)
+ if (session->ref == 0 && !session->streams && !session->req)
set_disconnect_timer(session);
if (session->streams && session->dc_timer)
@@ -2383,7 +2369,7 @@ static struct avdtp *avdtp_get_internal(const bdaddr_t *src, const bdaddr_t *dst
session->server = server;
bacpy(&session->dst, dst);
- session->ref = 1;
+ set_disconnect_timer(session);
/* We don't use avdtp_set_state() here since this isn't a state change
* but just setting of the initial state */
session->state = AVDTP_SESSION_STATE_DISCONNECTED;
--
1.7.11.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] avdtp: Fix crash on connection lost
2012-10-17 8:48 ` Luiz Augusto von Dentz
@ 2012-10-17 10:17 ` Szymon Janc
2012-10-17 10:32 ` Luiz Augusto von Dentz
0 siblings, 1 reply; 7+ messages in thread
From: Szymon Janc @ 2012-10-17 10:17 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth@vger.kernel.org
On Wednesday 17 of October 2012 11:48:36 Luiz Augusto von Dentz wrote:
> Hi Szymon,
Hi Luiz,
> >> We should probably get rid of the free_lock as well.
> >
> > Well, this is what this patch does, doesn't it?:)
>
> What about the attached patch, it should fix the references for good
> by using the dc_timer when the reference drops to 0, I just need to
> check if 1 second is enough to cover all cases including the ones
> where the remote device connects but doesn't setup any stream, with
> the devices I have 1 second seems enough.
Yeap, this fix crash I've observed.
However, avdtp_get_internal() now returns newly created session with ref=0
and in avdtp_confirm_cb() there is unref called when btd_request_authorization
failed. Due to ref being signed int (why?) this could lead to not-nice-to-debug
bug if that session is reclaimed before dc timer fires (ref would go from -1 to
0).
Also I'm having trouble with tracking lifetime of session object.. I think
only avdtp_ref/unref function should really care about ref count. That would
require other function to only use ref/unref to get/free session object.
e.g. avdtp_free should be only called from disconnect_timeout() and
connection_lost() should only trigger other session users to drop their
references. Same goes to set_disconnect_timer() which should only be called
from avdtp_unref. There should be no need to call connection_lost from
disconnect_timeout as this timer should only run when there is no references
held to that session, right?
Or do I miss something?:)
--
BR
Szymon Janc
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] avdtp: Fix crash on connection lost
2012-10-17 10:17 ` Szymon Janc
@ 2012-10-17 10:32 ` Luiz Augusto von Dentz
0 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2012-10-17 10:32 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth@vger.kernel.org
Hi Szymon,
On Wed, Oct 17, 2012 at 12:17 PM, Szymon Janc <szymon.janc@tieto.com> wrote:
> On Wednesday 17 of October 2012 11:48:36 Luiz Augusto von Dentz wrote:
>> Hi Szymon,
>
> Hi Luiz,
>
>> >> We should probably get rid of the free_lock as well.
>> >
>> > Well, this is what this patch does, doesn't it?:)
>>
>> What about the attached patch, it should fix the references for good
>> by using the dc_timer when the reference drops to 0, I just need to
>> check if 1 second is enough to cover all cases including the ones
>> where the remote device connects but doesn't setup any stream, with
>> the devices I have 1 second seems enough.
>
> Yeap, this fix crash I've observed.
>
> However, avdtp_get_internal() now returns newly created session with ref=0
> and in avdtp_confirm_cb() there is unref called when btd_request_authorization
> failed. Due to ref being signed int (why?) this could lead to not-nice-to-debug
> bug if that session is reclaimed before dc timer fires (ref would go from -1 to
> 0).
Good catch, I should be able to fix this, perhaps we can free
immediately or let the timeout handle this as well.
> Also I'm having trouble with tracking lifetime of session object.. I think
> only avdtp_ref/unref function should really care about ref count. That would
> require other function to only use ref/unref to get/free session object.
> e.g. avdtp_free should be only called from disconnect_timeout() and
> connection_lost() should only trigger other session users to drop their
> references. Same goes to set_disconnect_timer() which should only be called
> from avdtp_unref. There should be no need to call connection_lost from
> disconnect_timeout as this timer should only run when there is no references
> held to that session, right?
Well that involves changing some other logic behind the timeout, such as this:
if (session->ref == 0 && !session->streams && !session->req)
set_disconnect_timer(session);
if (session->streams && session->dc_timer)
remove_disconnect_timer(session);
IMO those should be removed in favor of the ref/unref handling if the
disconnect timer should be started/removed, if there is a request the
user should be holding a reference and the same for the stream, this
should actually simplify even further the code. Also the reason I did
avdtp_free in the connection_lost was not to much too much code around
as avdtp_free call a lot of other functions, but you are probably
right and this should actually be called from disconnect_timeout.
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2012-10-17 10:32 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-16 12:37 [PATCH] avdtp: Fix crash on connection lost Szymon Janc
2012-10-16 17:34 ` Luiz Augusto von Dentz
2012-10-16 17:43 ` Luiz Augusto von Dentz
2012-10-17 7:28 ` Szymon Janc
2012-10-17 8:48 ` Luiz Augusto von Dentz
2012-10-17 10:17 ` Szymon Janc
2012-10-17 10:32 ` Luiz Augusto von Dentz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox