From d7f7a5c3747baf9e0e689758e5ac7d9d1a386aab Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Wed, 3 Feb 2021 17:34:55 +0100 Subject: [PATCH] l2cap: make handling of hci disconnect more robust --- CHANGELOG.md | 1 + src/l2cap.c | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9178be36..ee1a3a9c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed AVDTP: emit stream release for active stream if signaling is closed first, e.g. caused by hci disconnect +L2CAP: make handling of hci disconnect more robust ### Changed diff --git a/src/l2cap.c b/src/l2cap.c index 451d5fade..09f6ea9d3 100644 --- a/src/l2cap.c +++ b/src/l2cap.c @@ -2384,14 +2384,22 @@ static void l2cap_handle_security_level(hci_con_handle_t handle, gap_security_le #ifdef L2CAP_USES_CHANNELS static void l2cap_handle_disconnection_complete(hci_con_handle_t handle){ + // collect channels to close + btstack_linked_list_t channels_to_close = NULL; btstack_linked_list_iterator_t it; - // send l2cap open failed or closed events for all channels on this handle and free them btstack_linked_list_iterator_init(&it, &l2cap_channels); - while (btstack_linked_list_iterator_has_next(&it)){ - l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); + while (btstack_linked_list_iterator_has_next(&it)) { + l2cap_channel_t *channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; if (channel->con_handle != handle) continue; btstack_linked_list_iterator_remove(&it); + btstack_linked_list_add(&channels_to_close, (btstack_linked_item_t *) channel); + } + // send l2cap open failed or closed events for all channels on this handle and free them + btstack_linked_list_iterator_init(&it, &channels_to_close); + while (btstack_linked_list_iterator_has_next(&it)) { + l2cap_channel_t *channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); + btstack_linked_list_iterator_remove(&it); switch(channel->channel_type){ #ifdef ENABLE_CLASSIC case L2CAP_CHANNEL_TYPE_CLASSIC: