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

casaroli 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 c066c4885ef sched/signal: Recheck pending sigtimedwait signals
c066c4885ef is described below

commit c066c4885ef522a0432e7cfa37bbcb3479a90eb7
Author: chao an <[email protected]>
AuthorDate: Wed Oct 28 14:46:54 2026 +0800

    sched/signal: Recheck pending sigtimedwait signals
    
    sigtimedwait() publishes sigwaitmask before nxsig_clockwait() moves the task
    to TSTATE_WAIT_SIG. A matching signal queued in that window can remain
    pending while the waiter goes to sleep.
    
    Recheck and consume matching pending signals in nxsig_clockwait() while
    interrupts are disabled before blocking the task.
    
    Signed-off-by: chao an <[email protected]>
---
 sched/signal/sig_clockwait.c | 28 ++++++++++++++++++++++++++++
 sched/signal/sig_timedwait.c |  1 +
 2 files changed, 29 insertions(+)

diff --git a/sched/signal/sig_clockwait.c b/sched/signal/sig_clockwait.c
index ee6f6595e85..50337e743e1 100644
--- a/sched/signal/sig_clockwait.c
+++ b/sched/signal/sig_clockwait.c
@@ -197,6 +197,8 @@ int nxsig_clockwait(int clockid, int flags,
   clock_t stop   = 0u;
 #ifndef CONFIG_DISABLE_ALL_SIGNALS
   siginfo_t unbinfo;
+  sigset_t intersection;
+  FAR sigpendq_t *sigpend;
   bool own_unbinfo = false;
 #endif
 
@@ -253,6 +255,32 @@ int nxsig_clockwait(int clockid, int flags,
       rtcb->sigunbinfo = &unbinfo;
       own_unbinfo = true;
     }
+
+  /* nxsig_timedwait() publishes sigwaitmask before calling this function.
+   * A matching signal can be queued after that publication but before this
+   * task transitions to TSTATE_WAIT_SIG. Re-check the pending set here while
+   * interrupts are disabled so we do not sleep with a waited-for signal
+   * already pending.
+   */
+
+  if (!own_unbinfo)
+    {
+      intersection = nxsig_pendingset(rtcb);
+      sigandset(&intersection, &intersection, &rtcb->sigwaitmask);
+      if (!sigisemptyset(&intersection))
+        {
+          sigpend = nxsig_remove_pendingsignal(rtcb,
+                                               nxsig_lowest(&intersection));
+          DEBUGASSERT(sigpend != NULL);
+
+          memcpy(rtcb->sigunbinfo, &sigpend->info, sizeof(siginfo_t));
+          sigemptyset(&rtcb->sigwaitmask);
+          nxsig_release_pendingsignal(sigpend);
+
+          leave_critical_section(iflags);
+          return 0;
+        }
+    }
 #endif
 
   if (rqtp)
diff --git a/sched/signal/sig_timedwait.c b/sched/signal/sig_timedwait.c
index 727120da1df..bd8daa0c6c1 100644
--- a/sched/signal/sig_timedwait.c
+++ b/sched/signal/sig_timedwait.c
@@ -176,6 +176,7 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct 
siginfo *info,
       ret = nxsig_clockwait(CLOCK_REALTIME, 0, timeout, NULL);
       if (ret < 0)
         {
+          sigemptyset(&rtcb->sigwaitmask);
           rtcb->sigunbinfo = NULL;
           return ret;
         }

Reply via email to