Commit Graph
4 Commits
Author SHA1 Message Date
Yunus Shaikh 780aa44726 fix(libkernel): block every word of a signal handler's mask while it runs
main now keeps all four words of the guest signal mask. A handler's sa_mask above signal 32 is added too, and SIGKILL and SIGSTOP stay unblocked, as sigprocmask leaves them.
2026-10-21 15:52:34 -07:00
Yunus Shaikh 9f584de29b test(libkernel): leave a signal handler with longjmp and raise it again
A handler that leaves with longjmp never returns to unblock its signal,
so longjmp has to bring back the mask setjmp saved before the signal.
2026-10-13 18:56:46 -07:00
Yunus Shaikh ef45904842 fix(libkernel): unblock only the signals a handler added when it returns
The blocked mask is still process-wide, so restoring the whole mask saved
before the handler undid any change another thread made while it ran.
2026-10-13 18:26:47 -07:00
Yunus Shaikh 3d1b4d460b fix(libkernel): block a signal while its handler runs and honour SA_RESETHAND
A guest signal handler ran with the mask it was raised under, so a
handler that raised its own signal again re-entered itself at once,
sigprocmask inside the handler did not report the signal or the
handler's sa_mask as blocked, and SA_RESETHAND left the handler
installed for the next delivery.

FreeBSD 11.4 forms the handler's frame and then, in postsig_done()
(sys/kern/kern_sig.c), blocks the handler's sa_mask and, unless
SA_NODEFER is set, the signal itself, and resets the disposition to
SIG_DFL when SA_RESETHAND is set; sigreturn restores the previous mask,
so a signal raised meanwhile stays pending until the handler returns.
sigaction keeps reporting SA_RESETHAND afterwards, since sigdflt() does
not clear ps_sigreset.

The handler now runs with its signal (unless SA_NODEFER) and its mask
added to the guest mask, which is restored when it returns, and pending
signals that the restored mask unblocks are delivered when raise
returns. SA_RESETHAND resets the handler to the default before it runs.
2026-10-13 09:47:28 -07:00