Skip to content

sched/signal: Run a synchronous signal handler out of the critical section. - #20640

Merged
xiaoxiang781216 merged 1 commit into
apache:masterfrom
casaroli:signal-handler-csection
Oct 16, 2026
Merged

xiaoxiang781216 merged 1 commit into
apache:masterfrom
casaroli:signal-handler-csection

Conversation

@casaroli

@casaroli casaroli commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Summary

When a signal with a handler is for the calling thread, nxsig_queue_action() runs the handler at once. It is called from nxsig_tcbdispatch(), which holds the critical section. So the handler runs with interrupts disabled, and on SMP its thread holds the global critical section lock until the handler returns.

In a protected or kernel build this happens at the end of each system call that leaves a pending signal unmasked: the user handler runs in user mode with interrupts disabled. Its CPU takes no interrupt, and the other CPUs wait for the critical section lock until the handler returns.

This PR lets nxsig_queue_action() only mark the delivery. nxsig_tcbdispatch() delivers after it leaves the critical section. A signal that an interrupt queues meanwhile is delivered in the same loop.

Impact

A handler that runs at once for the calling thread now runs with interrupts enabled and without the critical section. It still runs before nxsig_tcbdispatch() returns, so raise() and kill() of the calling thread behave as before.

Not changed here: nxsig_unmask_pendingsignal() holds sched_lock() while it dispatches, so such a handler still runs with preemption disabled.

Testing

qemu-armv8a:knsh, 1 CPU, with CONFIG_SCHED_IRQMONITOR=y. A test program blocks SIGUSR1, sends it to itself and unblocks it, so the handler runs at the end of sigprocmask(). The handler spins for about 50 ms and reads /proc/irqs before and after (a read returns the interrupts since the last read). Over 100 handlers:

master this PR
handlers that took no interrupt while they spun 100 0

ostest exits with status 0 on qemu-armv8a:knsh and on qemu-armv8a:nsh (flat build). Build: lm3s6965-ek:qemu-flat, no warnings.

…ction.

nxsig_queue_action() runs the signal handler at once when the signal is
for the calling thread.  It is called from nxsig_tcbdispatch(), which
holds the critical section.  In a kernel build this happens at the end
of each system call with a pending signal: the user handler then runs
in user mode with interrupts disabled, and on SMP its thread holds the
global critical section lock until the handler returns.  The other CPUs
wait for the lock all that time, and the CPU of the handler takes no
interrupt.

Let nxsig_queue_action() only mark the delivery, and deliver in
nxsig_tcbdispatch() after it leaves the critical section.  A signal that
an interrupt queues meanwhile is delivered in the same loop.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
@casaroli
casaroli requested a review from pussuw as a code owner October 13, 2026 16:27
@github-actions github-actions Bot added Area: OS Components OS Components issues Size: S The size of the change in this PR is small labels Oct 13, 2026
@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

MemBrowse Memory Report

esp32-devkitc

  • ROM: .flash.text +48 B (+0.0%, 125,968 B / 4,194,272 B, total: 3% used)
  • irom0_0_seg: .flash.text +48 B (+0.1%, 90,172 B / 3,342,304 B, total: 3% used)

qemu-armv8a

  • Code: .text.nxsig_tcbdispatch +60 B (+0.0%, 348,168 B)

qemu-intel64

  • Code: .text +64 B (+0.0%, 8,683,197 B)

rx65n-rsk2mb

  • ROM: .text +32 B (+0.0%, 87,284 B / 2,097,152 B, total: 4% used)

s698pm-dkit

@casaroli casaroli closed this Oct 14, 2026
@casaroli casaroli reopened this Oct 14, 2026
@casaroli casaroli closed this Oct 14, 2026
@casaroli casaroli reopened this Oct 14, 2026
@github-actions

Copy link
Copy Markdown

🔗 Cross-repo PR dependencies

The read-only Build run reported the following dependent PR(s) and fetched head SHA(s):

CI run: https://github.com/apache/nuttx/actions/runs/38593989522

@casaroli casaroli closed this Oct 15, 2026
@casaroli casaroli reopened this Oct 15, 2026
@casaroli casaroli closed this Oct 15, 2026
@casaroli casaroli reopened this Oct 15, 2026
@xiaoxiang781216
xiaoxiang781216 merged commit 4b2aaf8 into apache:master Oct 16, 2026
202 of 318 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: OS Components OS Components issues Size: S The size of the change in this PR is small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants