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 */

Reply via email to