aboutsummaryrefslogtreecommitdiff
path: root/cddl/sbin/tests
diff options
context:
space:
mode:
authorGrzegorz Junka <list1@gjunka.com>2026-09-27 19:22:20 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2026-09-27 19:22:20 +0000
commit16a284b1cdfd45ba99c2723e7f88497e76b235ad (patch)
tree60deb76a369b3855f0aaff2f5de81aeba3363f8f /cddl/sbin/tests
parent1d94247d0e3fe79fee7902383d27f51b089beb0d (diff)
linux(4): Fix signal mask restoration in epoll_pwait(2)/epoll_pwait2(2)HEADmain
Since 80c7315d17ce ("Restore signal mask in epoll_pwait.") the caller's signal mask is saved in a local variable, but TDP_OLDMASK is still set and the TDA_SIGSUSPEND AST is still scheduled. On return to user mode that AST, or postsig() if a signal is delivered, then installs td_oldsigmask, which this code never writes and which holds whatever mask the thread had at its last sigsuspend(2), pselect(2) or ppoll(2). As a result every epoll_pwait(2)/epoll_pwait2(2) call with a non-NULL sigmask can leave the thread with a stale signal mask. In addition, the explicit restore at the end overwrote the return value, so EINTR (and any other error) was reported to user space as 0. Save the old mask in td_oldsigmask and let the AST restore it, as kern_pselect() and kern_poll_kfds() do: schedule TDA_SIGSUSPEND if the wait was interrupted, so the signal is delivered with the temporary mask in place, and TDA_PSELECT otherwise. This matches Linux, which restores the saved mask unless the syscall returns -EINTR. This deadlocks Bun-based programs such as Claude Code (>= 2.1.269) and opencode. JavaScriptCore suspends threads for conservative GC stack scanning by sending SIGPWR and waiting for the target's handler, which calls sigsuspend(2) with SIGPWR blocked. Afterwards td_oldsigmask contains SIGPWR, the event loop's next epoll_pwait2(2) (Bun always passes an empty sigmask) blocks SIGPWR on the main thread, and the next GC suspend request waits forever. PR: 298878 Fixes: 80c7315d17ce ("Restore signal mask in epoll_pwait.") MFC after: 1 week
Diffstat (limited to 'cddl/sbin/tests')
0 files changed, 0 insertions, 0 deletions