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;
}