Skip to content

fix(libkernel): discard a pending signal when sigaction or signal ignores it - #9123

Open
Retr0G28 wants to merge 1 commit into
boykopovar:mainfrom
Retr0G28:fix/sigaction-ignore-discards-pending
Open

Retr0G28 wants to merge 1 commit into
boykopovar:mainfrom
Retr0G28:fix/sigaction-ignore-discards-pending

Conversation

@Retr0G28

@Retr0G28 Retr0G28 commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What

Setting SIG_IGN with sigaction or signal, or SIG_DFL on a signal whose default action is to ignore, left a signal that was already pending on the pending set. Unblocking it later ran whatever handler was installed by then, and sigwait could still take it. FreeBSD 11's kern_sigaction (sys/kern/kern_sig.c) calls sigqueue_delete_proc in that case, which removes the signal from the process queue and from every thread's queue, blocked or not. The signals whose sigprop has SA_IGNORE are SIGURG, SIGCONT, SIGCHLD, SIGIO, SIGWINCH and SIGINFO; sigprop returns 0 for 32 and above, so no real-time signal is ignored by default. That is the same list IgnoredByDefault already uses.

sigaction and signal now remove the signal from the process-wide pending set after recording such a disposition. SIGCONT is discarded too, as in kern_sigaction, which only keeps it out of ps_sigignore. The error paths (invalid numbers, a handler on SIGKILL or SIGSTOP) return before anything changes, as before. The clause about this gap is cut from the sigpending entry in docs/dev/debt/libkernel.md.

Test changes:

  • guest_signals blocks signal 30, raises it with a handler installed, and checks that SIG_DFL keeps it pending, SIG_IGN through sigaction and through signal removes it, and unblocking afterwards with the handler reinstalled does not run it. It does the same for SIGWINCH with SIG_DFL, and for a blocked SIGCONT raised with the default disposition and reset with signal(SIGCONT, SIG_DFL).

Tested

Windows 11, WinLibs MinGW-w64 GCC 15.2.0 r7, CMake + Ninja, Release, -DBUILD_TESTING=ON, on main 2f161d4.

  • Before the fix, guest_signals with the new checks fails (exit 0xc0000409) at the sigpending check right after sigaction(30, SIG_IGN), which still reports signal 30. With this PR it passes.
  • guest_signals, guest_sigtimedwait, guest_itimer, guest_itimer_pending_default, guest_signal_sets, guest_sigaltstack, guest_getitimer, guest_kill, guest_signal_list, guest_raise_exception and guest_raise_nested_sleep: 11 of 11 pass when run serially.
  • python tools/check_conventions.py --base origin/main reports no errors.
  • Linux: @xXPBSXx ran the PR head on WSL2 Ubuntu 24.04 (GCC 13.3.0): guest_signals passes, and fails with main's Signals.cpp (comment below). Not run on bare-metal Linux.
  • No title or homebrew run.

Overlap: tools/pr_overlap.py reports #8866, #8872 and #9001, which append tests at the same place at the end of GuestSignals.cpp (signal and siginterrupt with SA_RESTART); none of them discards pending signals. It could not compare #3986 (per-thread signal mask) and #7201 (macOS port) on Signals.cpp; #3986 drops an ignored signal only when it is raised, not when the disposition changes, and #7201 does not touch this logic. The rest touch only other lines of docs/dev/debt/libkernel.md.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

…ores it

FreeBSD 11's kern_sigaction (sys/kern/kern_sig.c) calls
sigqueue_delete_proc, which drops the signal from the process queue and
from every thread's queue, whenever the new handler is SIG_IGN, or
SIG_DFL on a signal whose sigprop has SA_IGNORE (SIGURG, SIGCONT,
SIGCHLD, SIGIO, SIGWINCH, SIGINFO). It does so whether or not the
signal is blocked. sigaction and signal now take the signal off the
pending set in those cases, so a later unblock or wait never sees it.
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 8866 core/libs/tests/GuestSignals.cpp L400
PR 8872 core/libs/tests/GuestSignals.cpp L400
PR 9001 core/libs/tests/GuestSignals.cpp L400

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 3986 core/libs/prx/libkernel/System/src/Signals.cpp
core/libs/tests/GuestSignals.cpp
PR 5021 docs/dev/debt/libkernel.md
PR 6044 core/libs/tests/GuestSignals.cpp
PR 6149 docs/dev/debt/libkernel.md
PR 6469 docs/dev/debt/libkernel.md
PR 6740 docs/dev/debt/libkernel.md
PR 6830 docs/dev/debt/libkernel.md
PR 6879 docs/dev/debt/libkernel.md
PR 7088 docs/dev/debt/libkernel.md
PR 7105 docs/dev/debt/libkernel.md
PR 7149 docs/dev/debt/libkernel.md
PR 7201 core/libs/prx/libkernel/System/src/Signals.cpp
PR 7447 docs/dev/debt/libkernel.md
PR 7509 docs/dev/debt/libkernel.md
PR 7565 docs/dev/debt/libkernel.md
PR 7605 docs/dev/debt/libkernel.md
PR 7622 core/libs/prx/libkernel/System/src/Signals.cpp
PR 7653 docs/dev/debt/libkernel.md
PR 8373 docs/dev/debt/libkernel.md
PR 8520 docs/dev/debt/libkernel.md
PR 8553 docs/dev/debt/libkernel.md
PR 8670 docs/dev/debt/libkernel.md
PR 8921 docs/dev/debt/libkernel.md
PR 9392 docs/dev/debt/libkernel.md
PR 9509 docs/dev/debt/libkernel.md

@xXPBSXx

xXPBSXx commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Linux data point for bbfa163722: WSL2 Ubuntu 24.04 (virtualised kernel, not bare-metal Linux), GCC 13.3.0, Release, BUILD_TESTING=ON, PR head alone (not merged onto main) (its merge-base is 2f161d4f3).

  • With the PR: ctest -R '^guest_signals$' passes 3 of 3.
  • With the production files of the PR restored to the merge-base (core/libs/prx/libkernel/System/src/Signals.cpp; the PR's tests kept): fails (Subprocess aborted).
    Not tested: macOS, Windows, a title run.
    AI-assisted (Claude Code).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants