src: Discriminate FreeBSD rescue-timer SIGINTs and bound abandon delivery
Two delivery-robustness fixes found chasing the cancellation test failures
on the slower CI platforms:
FreeBSD selects the POSIX-timer rescue mechanism, whose SIGINT is told
apart from a user press by sigwaitinfo's SI_TIMER si_code - but every
sigwaitinfo use was guarded by _POSIX_C_SOURCE >= 199309L, which glibc
defines through _GNU_SOURCE and FreeBSD does not define at all. The
signal listener there fell back to plain sigwait, so a rescue-timer
expiry was indistinguishable from a user ^C: no escalation warning could
ever print, the expiry was never recorded (so the direct-abandonment gate
never opened), and each phantom "press" re-armed the timer. That left the
REPL pty ladder on FreeBSD completely dead after the first press. Gate
these paths on a new HAVE_SIGWAITINFO that includes FreeBSD, where
sigwaitinfo is available regardless of the feature macro.
jl_abandon_task's delivery-retry loop was bounded by iteration count
(200 sends x 10 x uv_sleep(1)), nominally ~2s - but every uv_sleep is a
reschedule, and on an oversubscribed or serialized machine (CI under
load, rr) the loop stretched to minutes per call. The unsafe_abandon!
testsets spam that call in a 20s wall-clock loop, blowing through the
parent's subprocess watchdog on the rr job. Bound the loop by wall clock
instead.
Relatedly, jl_thread_suspend_and_get_state asserted the per-thread signal
request slot held no request, but a parked best-effort cancellation (5)
or abandon (6) whose victim never consumes signals (e.g. SIGUSR2 blocked)
can occupy it indefinitely; both senders tolerate a displaced delivery.
Seen as an abort in assert builds when a termination signal arrived while
an abandon request was pending.
CI failure: https://buildkite.com/julialang/julia-pr/builds/392#019f59bc-6691-42e6-aa26-0fe946612248
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015KLwCBAR64r3cTdfaC5krU