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
