From 5f6e1e2d7ee053c446ad06f6909c0e9a94520e40 Mon Sep 17 00:00:00 2001 From: Shunchao Hu Date: Fri, 3 Apr 2026 22:42:57 +0800 Subject: [PATCH] sched/semaphore: check unmasked pending signals before blocking. A signal can arrive before sem_wait transitions the task to 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. Check for unmasked pending signals before touching the semaphore count and return -EINTR if one is already pending. Signed-off-by: Shunchao Hu --- sched/semaphore/sem_wait.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sched/semaphore/sem_wait.c b/sched/semaphore/sem_wait.c index fe710be58b3..aac400ddd32 100644 --- a/sched/semaphore/sem_wait.c +++ b/sched/semaphore/sem_wait.c @@ -34,6 +34,9 @@ #include #include #include +#ifdef CONFIG_ENABLE_ALL_SIGNALS +#include +#endif #include "sched/sched.h" #include "semaphore/semaphore.h" @@ -71,6 +74,9 @@ int nxsem_wait_slow(FAR sem_t *sem) { +#ifdef CONFIG_ENABLE_ALL_SIGNALS + sigset_t pendingset; +#endif FAR struct tcb_s *rtcb = this_task(); irqstate_t flags; int ret = OK; @@ -87,6 +93,22 @@ int nxsem_wait_slow(FAR sem_t *sem) /* Make sure we were supplied with a valid semaphore. */ +#ifdef CONFIG_ENABLE_ALL_SIGNALS + /* A signal can arrive before sem_wait transitions the task to + * 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. + */ + + pendingset = nxsig_pendingset(rtcb); + nxsig_nandset(&pendingset, &pendingset, &rtcb->sigprocmask); + if (!sigisemptyset(&pendingset)) + { + leave_critical_section(flags); + return -EINTR; + } +#endif + /* Check if the lock is available */ if (mutex)