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

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

commit 892c24d9b268f235d4775600e7fd69a872bc5e83
Author: Marco Casaroli <[email protected]>
AuthorDate: Tue Oct 13 10:29:26 2026 +0200

    sched/semaphore: Do not fail a mutex wait for a pending signal.
    
    nxsem_wait_slow() returns -EINTR at once when an unmasked signal is
    pending, so that a signal that arrives just before the task blocks
    still interrupts the wait.  During a system call, an unmasked signal
    stays pending until the call returns.  Kernel code retries a mutex wait
    until it gets the mutex, as mm_lock() does, so each retry failed at once
    and the task looped.  If it looped in a critical section, the task that
    held the mutex could not run.
    
    On a 4-CPU arm64 SMP target, a task in pselect() with SIGCHLD pending
    freed a pending signal with kmm_free(), and mm_lock() looped in
    pselect()'s critical section while the other CPUs waited for it.
    
    Do not make this check for a mutex.  A mutex wait is not interrupted by
    a signal, and a signal that arrives while the task waits still wakes it
    through nxsem_wait_irq().
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 sched/semaphore/sem_wait.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/sched/semaphore/sem_wait.c b/sched/semaphore/sem_wait.c
index 7481b2fa7c9..3493048af98 100644
--- a/sched/semaphore/sem_wait.c
+++ b/sched/semaphore/sem_wait.c
@@ -96,14 +96,22 @@ int nxsem_wait_slow(FAR sem_t *sem)
    * TSTATE_WAIT_SEM. In that window, the wait cannot yet be aborted by
    * sem_wait_irq(). If sem_wait then blocks without re-checking unmasked
    * pending signals, it can sleep indefinitely and miss the interrupt.
+   *
+   * Not for a mutex: a mutex wait is not interrupted by a signal, and the
+   * kernel retries it until it gets the mutex (mm_lock(), for example).
+   * During a system call an unmasked signal stays pending until the call
+   * returns, so the check would make every retry fail at once.
    */
 
-  pendingset = nxsig_pendingset(rtcb);
-  nxsig_nandset(&pendingset, &pendingset, &rtcb->sigprocmask);
-  if (!sigisemptyset(&pendingset))
+  if (!mutex)
     {
-      leave_critical_section(flags);
-      return -EINTR;
+      pendingset = nxsig_pendingset(rtcb);
+      nxsig_nandset(&pendingset, &pendingset, &rtcb->sigprocmask);
+      if (!sigisemptyset(&pendingset))
+        {
+          leave_critical_section(flags);
+          return -EINTR;
+        }
     }
 #endif
 

Reply via email to