You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2026/10/23 00:45:42 UTC
(nuttx) branch master updated (dd8c234ad82 -> ef611627a5c)
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
from dd8c234ad82 drivers/analog: add MCP45XX potentiometer support
new 278db9783a4 sched/signal: Restore the mask of pselect() after its signals are dispatched.
new ef611627a5c Documentation: Describe when sigsuspend() restores the signal mask.
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
Documentation/reference/user/07_signals.rst | 5 +-
include/nuttx/sched.h | 2 +
sched/signal/sig_ppoll.c | 4 +-
sched/signal/sig_pselect.c | 4 +-
sched/signal/sig_suspend.c | 4 +-
sched/signal/sig_unmaskpendingsignal.c | 76 +++++++++++++++++++++++++++--
sched/signal/signal.h | 2 +
7 files changed, 85 insertions(+), 12 deletions(-)
(nuttx) 01/02: sched/signal: Restore the mask of pselect() after its signals are dispatched.
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 278db9783a43c4231b10092ef6d7198e86d3a424
Author: Marco Casaroli <ma...@gmail.com>
AuthorDate: Tue Oct 13 13:12:33 2026 +0200
sched/signal: Restore the mask of pselect() after its signals are dispatched.
pselect(), ppoll() and sigsuspend() install a temporary signal mask and
restore the old one before they return. In a system call, a signal
that the temporary mask unblocks is not delivered at once: it goes back
on the list of pending signals, to be dispatched at the end of the
system call. By then the old mask was restored, so a signal that the
old mask blocks stayed pending, and its handler never ran. Every later
pselect() found it and returned EINTR at once.
For example, a program that blocks SIGCHLD and unblocks it only in
pselect() never runs its SIGCHLD handler, and its pselect() loop spins.
In a system call, keep the temporary mask and save the old one in the
TCB. nxsig_unmask_pendingsignal(), at the end of the system call,
dispatches the pending signals with the temporary mask, which queues
their actions, and then restores the old mask. Outside a system call
the mask is restored at once, as before.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <ma...@gmail.com>
---
include/nuttx/sched.h | 2 +
sched/signal/sig_ppoll.c | 4 +-
sched/signal/sig_pselect.c | 4 +-
sched/signal/sig_suspend.c | 4 +-
sched/signal/sig_unmaskpendingsignal.c | 76 ++++++++++++++++++++++++++++++++--
sched/signal/signal.h | 2 +
6 files changed, 82 insertions(+), 10 deletions(-)
diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h
index e77cd69ef84..053a2995f29 100644
--- a/include/nuttx/sched.h
+++ b/include/nuttx/sched.h
@@ -112,6 +112,7 @@
#define TCB_FLAG_JOIN_COMPLETED (1 << 14) /* Bit 14: Pthread join completed */
#define TCB_FLAG_FREE_TCB (1 << 15) /* Bit 15: Free tcb after exit */
#define TCB_FLAG_PREEMPT_SCHED (1 << 16) /* Bit 16: tcb is PREEMPT_SCHED */
+#define TCB_FLAG_SIGMASK_SAVED (1 << 17) /* Bit 17: sigsavedmask to restore */
/* Values for struct task_group tg_flags */
@@ -702,6 +703,7 @@ struct tcb_s
#ifndef CONFIG_DISABLE_ALL_SIGNALS
sigset_t sigprocmask; /* Signals that are blocked */
sigset_t sigwaitmask; /* Waiting for pending signals */
+ sigset_t sigsavedmask; /* Mask to restore at syscall exit */
siginfo_t *sigunbinfo; /* Signal info when task unblocked */
#endif /* !CONFIG_DISABLE_ALL_SIGNALS */
diff --git a/sched/signal/sig_ppoll.c b/sched/signal/sig_ppoll.c
index c320bc1967d..567a4d9f3ef 100644
--- a/sched/signal/sig_ppoll.c
+++ b/sched/signal/sig_ppoll.c
@@ -105,7 +105,7 @@ int ppoll(FAR struct pollfd *fds, nfds_t nfds,
* us to not wait. Restore the original sigprocmask.
*/
- rtcb->sigprocmask = saved_sigprocmask;
+ nxsig_restoremask(rtcb, &saved_sigprocmask);
leave_critical_section(flags);
set_errno(EINTR);
}
@@ -125,7 +125,7 @@ int ppoll(FAR struct pollfd *fds, nfds_t nfds,
/* We are running again, restore the original sigprocmask */
- rtcb->sigprocmask = saved_sigprocmask;
+ nxsig_restoremask(rtcb, &saved_sigprocmask);
leave_critical_section(flags);
/* Now, handle the (rare?) case where (a) a blocked signal was received
diff --git a/sched/signal/sig_pselect.c b/sched/signal/sig_pselect.c
index c660e379d11..b28096d12e6 100644
--- a/sched/signal/sig_pselect.c
+++ b/sched/signal/sig_pselect.c
@@ -102,7 +102,7 @@ int pselect(int nfds, FAR fd_set *readfds, FAR fd_set *writefds,
* us to not wait. Restore the original sigprocmask.
*/
- rtcb->sigprocmask = saved_sigprocmask;
+ nxsig_restoremask(rtcb, &saved_sigprocmask);
leave_critical_section(flags);
set_errno(EINTR);
}
@@ -124,7 +124,7 @@ int pselect(int nfds, FAR fd_set *readfds, FAR fd_set *writefds,
/* We are running again, restore the original sigprocmask */
- rtcb->sigprocmask = saved_sigprocmask;
+ nxsig_restoremask(rtcb, &saved_sigprocmask);
leave_critical_section(flags);
/* Now, handle the (rare?) case where (a) a blocked signal was received
diff --git a/sched/signal/sig_suspend.c b/sched/signal/sig_suspend.c
index d7d14b52f00..4cd623b09ab 100644
--- a/sched/signal/sig_suspend.c
+++ b/sched/signal/sig_suspend.c
@@ -114,7 +114,7 @@ int sigsuspend(FAR const sigset_t *set)
* us to not wait. Restore the original sigprocmask.
*/
- rtcb->sigprocmask = saved_sigprocmask;
+ nxsig_restoremask(rtcb, &saved_sigprocmask);
leave_critical_section(flags);
}
else
@@ -141,7 +141,7 @@ int sigsuspend(FAR const sigset_t *set)
/* We are running again, restore the original sigprocmask */
- rtcb->sigprocmask = saved_sigprocmask;
+ nxsig_restoremask(rtcb, &saved_sigprocmask);
leave_critical_section(flags);
/* Now, handle the (rare?) case where (a) a blocked signal was received
diff --git a/sched/signal/sig_unmaskpendingsignal.c b/sched/signal/sig_unmaskpendingsignal.c
index 704dad82a1d..1f79ea8420b 100644
--- a/sched/signal/sig_unmaskpendingsignal.c
+++ b/sched/signal/sig_unmaskpendingsignal.c
@@ -34,11 +34,11 @@
#include "signal/signal.h"
/****************************************************************************
- * Public Functions
+ * Private Functions
****************************************************************************/
/****************************************************************************
- * Name: nxsig_unmask_pendingsignal
+ * Name: nxsig_dispatch_unmasked
*
* Description:
* Based upon the current setting of the sigprocmask, this function
@@ -47,9 +47,8 @@
*
****************************************************************************/
-bool nxsig_unmask_pendingsignal(void)
+static bool nxsig_dispatch_unmasked(FAR struct tcb_s *rtcb)
{
- FAR struct tcb_s *rtcb = this_task();
sigset_t unmaskedset;
FAR sigpendq_t *pendingsig;
int signo;
@@ -118,3 +117,72 @@ bool nxsig_unmask_pendingsignal(void)
sched_unlock();
return true;
}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nxsig_unmask_pendingsignal
+ *
+ * Description:
+ * Dispatch the pending signals that the signal mask of the calling thread
+ * does not block. At the end of a system call, also restore the mask
+ * that nxsig_restoremask() saved, after the signals that the temporary
+ * mask of pselect(), ppoll() or sigsuspend() unblocks are dispatched.
+ *
+ * Returned Value:
+ * true if one or more signals were dispatched.
+ *
+ ****************************************************************************/
+
+bool nxsig_unmask_pendingsignal(void)
+{
+ FAR struct tcb_s *rtcb = this_task();
+ bool dispatched;
+
+ dispatched = nxsig_dispatch_unmasked(rtcb);
+
+ if ((rtcb->flags & (TCB_FLAG_SYSCALL | TCB_FLAG_SIGMASK_SAVED)) ==
+ TCB_FLAG_SIGMASK_SAVED)
+ {
+ rtcb->sigprocmask = rtcb->sigsavedmask;
+ rtcb->flags &= ~TCB_FLAG_SIGMASK_SAVED;
+
+ if (nxsig_dispatch_unmasked(rtcb))
+ {
+ dispatched = true;
+ }
+ }
+
+ return dispatched;
+}
+
+/****************************************************************************
+ * Name: nxsig_restoremask
+ *
+ * Description:
+ * Restore the signal mask after the temporary mask of pselect(), ppoll()
+ * or sigsuspend(). In a system call, a signal that the temporary mask
+ * unblocked is still on the pending list: it is dispatched only at the
+ * end of the system call. So keep the temporary mask until then, and
+ * let nxsig_unmask_pendingsignal() restore this one.
+ *
+ * Input Parameters:
+ * rtcb - The calling thread.
+ * mask - The signal mask to restore.
+ *
+ ****************************************************************************/
+
+void nxsig_restoremask(FAR struct tcb_s *rtcb, FAR const sigset_t *mask)
+{
+ if ((rtcb->flags & TCB_FLAG_SYSCALL) != 0)
+ {
+ rtcb->sigsavedmask = *mask;
+ rtcb->flags |= TCB_FLAG_SIGMASK_SAVED;
+ }
+ else
+ {
+ rtcb->sigprocmask = *mask;
+ }
+}
diff --git a/sched/signal/signal.h b/sched/signal/signal.h
index 46f64d56a52..1de4b8b66a8 100644
--- a/sched/signal/signal.h
+++ b/sched/signal/signal.h
@@ -213,6 +213,8 @@ FAR sigpendq_t *nxsig_remove_pendingsignal(FAR struct tcb_s *stcb,
int signo);
#ifndef CONFIG_DISABLE_ALL_SIGNALS
bool nxsig_unmask_pendingsignal(void);
+void nxsig_restoremask(FAR struct tcb_s *rtcb,
+ FAR const sigset_t *mask);
#else
static inline bool nxsig_unmask_pendingsignal(void)
{
(nuttx) 02/02: Documentation: Describe when sigsuspend() restores the signal mask.
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit ef611627a5cc5100c7c62d00985f1c6cd85d3e9a
Author: Marco Casaroli <ma...@gmail.com>
AuthorDate: Sat Oct 17 20:42:05 2026 +0200
Documentation: Describe when sigsuspend() restores the signal mask.
sigsuspend() runs the handlers of the signals that its mask unblocks
before it restores the original mask, also in a system call. The page
did not say this, and it listed the restore of the mask as a difference
from POSIX, which requires it.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <ma...@gmail.com>
---
Documentation/reference/user/07_signals.rst | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Documentation/reference/user/07_signals.rst b/Documentation/reference/user/07_signals.rst
index 718362a3371..236a4e4997d 100644
--- a/Documentation/reference/user/07_signals.rst
+++ b/Documentation/reference/user/07_signals.rst
@@ -386,7 +386,9 @@ provided by NuttX:
If the effect of the set argument is to unblock a pending signal, then
no wait is performed.
- The original signal mask is restored when sigsuspend() returns.
+ The original signal mask is restored when sigsuspend() returns. The
+ handlers of the signals that ``set`` unblocks run first, with ``set``
+ still installed, also when sigsuspend() is a system call.
Waiting for an empty signal set stops a task without freeing any
resources (a very bad idea).
@@ -398,7 +400,6 @@ provided by NuttX:
**POSIX Compatibility:** Comparable to the POSIX interface of the same
name. Differences from the POSIX specification include:
- - POSIX does not indicate that the original signal mask is restored.
- POSIX states that sigsuspend() "suspends the task until delivery of a
signal whose action is either to execute a signal-catching function
or to terminate the task." Only delivery of the signal is required in