This is an automated email from the ASF dual-hosted git repository.

sjanc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git


The following commit(s) were added to refs/heads/master by this push:
     new 9ca0c718f host: Fix recursive lock in ble_hs_stop_done
9ca0c718f is described below

commit 9ca0c718f05a0456507051bc91121d34314f610b
Author: Deomid rojer Ryabkov <[email protected]>
AuthorDate: Fri Apr 17 23:59:10 2026 +0300

    host: Fix recursive lock in ble_hs_stop_done
    
    ble_hs_stop_done() held ble_hs_lock while calling ble_gap_reset_state()
    which acquires the same lock via ble_hs_atomic_first_conn_handle()
    and ble_gap_conn_broken(). On platforms with non-recursive mutexes this
    causes a deadlock or assertion failure.
    
    Move ble_hs_stop_hci_reset(), ble_gap_reset_state(), ble_hs_id_reset(),
    and ble_hs_pvcy_reset() outside the locked section. These functions
    either manage their own locking internally or don't need the lock.
    ble_hs_enabled_state is set to OFF under the lock before releasing,
    preventing new operations.
---
 nimble/host/src/ble_hs_stop.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/nimble/host/src/ble_hs_stop.c b/nimble/host/src/ble_hs_stop.c
index c0ff67e45..861086520 100644
--- a/nimble/host/src/ble_hs_stop.c
+++ b/nimble/host/src/ble_hs_stop.c
@@ -69,9 +69,14 @@ ble_hs_stop_done(int status)
 
     ble_hs_enabled_state = BLE_HS_ENABLED_STATE_OFF;
 
+    ble_hs_unlock();
+
     ble_hs_stop_hci_reset();
 
-    /* Clear advertising, scanning and connection states. */
+    /* Clear advertising, scanning and connection states.
+     * Called outside the lock because ble_gap_reset_state() acquires
+     * it internally (via ble_gap_conn_broken, ble_hs_atomic_*, etc).
+     */
     ble_gap_reset_state(0);
 
     /* After LL reset the controller loses its random address */
@@ -79,8 +84,6 @@ ble_hs_stop_done(int status)
 
     ble_hs_pvcy_reset();
 
-    ble_hs_unlock();
-
     SLIST_FOREACH(listener, &slist, link) {
         listener->fn(status, listener->arg);
     }

Reply via email to