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

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new c3d8565a3b2 wireless/bluetooth: Clear the sync reference when a 
command times out.
c3d8565a3b2 is described below

commit c3d8565a3b24918de7196fa0b955b9313ca939d0
Author: Alan Carvalho de Assis <[email protected]>
AuthorDate: Thu Sep 17 10:22:36 2026 -0300

    wireless/bluetooth: Clear the sync reference when a command times out.
    
    bt_hci_cmd_send_sync() puts a semaphore on its own stack and stores a
    pointer to it in the command buffer, so that the completion handler can
    wake it.  On timeout it destroyed that semaphore and returned without
    clearing the stored pointer, while g_btdev.sent_cmd still referred to the
    same buffer.  A Command Complete or Command Status arriving after the
    timeout therefore reached hci_cmd_done(), found the pointer and posted a
    semaphore belonging to a stack frame that had already returned.  The
    comment just below the timeout already observed that the packet may still
    be in flight.
    
    Detach the semaphore from the buffer, and drop the pending command that
    refers to that buffer, before destroying it.
    
    This narrows the window rather than closing it: the completion runs in
    another context and shares no lock with this one.  Removing the race
    needs a command queue with per-command state, which is a larger change,
    and the code now says so where it matters.
    
    Ref: Core v6.0, Vol 4, Part E, 7.7.14 (Command Complete event)
    Ref: Core v6.0, Vol 4, Part E, 7.7.15 (Command Status event)
    Testing: builds for sim:bluetooth with Make; every commit in this series
    verified to build individually.  Not yet exercised at runtime - the
    scriptable controller can withhold a completion past the host timeout,
    and that case is added separately.
    
    Signed-off-by: Alan C. Assis <[email protected]>
    Assisted-by: Claude Code Opus 5
---
 wireless/bluetooth/bt_hcicore.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/wireless/bluetooth/bt_hcicore.c b/wireless/bluetooth/bt_hcicore.c
index cf8625d80e3..7496d2962d5 100644
--- a/wireless/bluetooth/bt_hcicore.c
+++ b/wireless/bluetooth/bt_hcicore.c
@@ -2184,6 +2184,27 @@ int bt_hci_cmd_send_sync(uint16_t opcode, FAR struct 
bt_buf_s *buf,
   else
     {
       wlerr("ERROR:  Failed get response\n");
+
+      /* The command timed out, and sync_sem is about to go out of scope.
+       * A completion arriving after this point would still find the
+       * pointer to it in the command buffer and post it, so detach it
+       * from the buffer, and from the pending command that still refers
+       * to the buffer, before destroying it.
+       *
+       * This closes the window rather than removing it: the completion
+       * runs in another context and there is no lock shared with it.  A
+       * race-free version needs the command queue with per-command state
+       * that is planned separately.
+       */
+
+      buf->u.hci.sync = NULL;
+
+      if (g_btdev.sent_cmd == buf)
+        {
+          g_btdev.sent_cmd = NULL;
+          bt_buf_release(buf);
+        }
+
       nxsem_destroy(&sync_sem);
       return -EIO;
     }

Reply via email to