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 eb2154e41eae1d35e96477c849f8e5b764716387 Author: ganjing <[email protected]> AuthorDate: Wed Nov 11 16:29:01 2026 +0800 sched/signal: remove pending signals when setting handler to SIG_IGN POSIX requires that setting the disposition of a pending signal to SIG_IGN discards the pending signal, whether or not it is blocked. The SIG_IGN path only removed the previous sigaction container and left the matching entries queued in the group pending list, so a signal that had just been ignored stayed pending forever. Collect the matching entries under the group lock and release them after dropping it; nxsig_release_pendingsignal() cannot run under the lock because it takes a different spinlock and may free memory. Signed-off-by: ganjing <[email protected]> Signed-off-by: zhangyuan29 <[email protected]> --- sched/signal/sig_action.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/sched/signal/sig_action.c b/sched/signal/sig_action.c index 45381f0906c..8e18a6c71b7 100644 --- a/sched/signal/sig_action.c +++ b/sched/signal/sig_action.c @@ -215,6 +215,8 @@ int nxsig_action(int signo, FAR const struct sigaction *act, FAR struct tcb_s *rtcb = this_task(); FAR struct task_group_s *group; FAR sigactq_t *sigact; + FAR sigpendq_t *sigpend; + sq_queue_t sigpendq; _sa_handler_t handler; irqstate_t flags; @@ -233,6 +235,10 @@ int nxsig_action(int signo, FAR const struct sigaction *act, return -EINVAL; } + /* Initialize a queue to collect pending signals that need to be released */ + + sq_init(&sigpendq); + /* Verify the signal number */ if (!GOOD_SIGNO(signo)) @@ -368,6 +374,49 @@ int nxsig_action(int signo, FAR const struct sigaction *act, nxsig_release_action(sigact); } + + flags = spin_lock_irqsave(&group->tg_lock); + + /* Traverse the pending signal queue + * to find signals with matching signo + */ + + sigpend = (FAR sigpendq_t *)group->tg_sigpendingq.head; + while (sigpend) + { + FAR sigpendq_t *next_sigpend = sigpend->flink; + + if (sigpend->info.si_signo == signo) + { + /* Remove the pending signal from the group's pending queue */ + + sq_rem((FAR sq_entry_t *)sigpend, &group->tg_sigpendingq); + + /* Add it to the temporary queue for later release + * We cannot call nxsig_release_pendingsignal() here: it + * enters a critical section and may call kmm_free(), and + * neither may happen while holding the group spinlock + * (the critical section would nest with tg_lock). + */ + + sq_addlast((FAR sq_entry_t *)sigpend, &sigpendq); + } + + sigpend = next_sigpend; + } + + spin_unlock_irqrestore(&group->tg_lock, flags); + + /* Now release the collected pending signals outside the spinlock */ + + sigpend = (FAR sigpendq_t *)sigpendq.head; + while (sigpend) + { + FAR sigpendq_t *next_sigpend = sigpend->flink; + + nxsig_release_pendingsignal(sigpend); + sigpend = next_sigpend; + } } /* A sigaction has been supplied */
