base: Deliver ^C notifications while the io thread runs foreign code
Outside a threaded region, only the io thread is permitted to run the
libuv event loop; every other idle thread parks after poking it. When
the io thread is blocked in a long-running foreign call (e.g. a large
BLAS operation typed at the REPL), the entire event loop therefore
stalls - including the AsyncCondition that wakes the sigint listener -
so a ^C sat undelivered until the foreign call returned, defeating the
cancellation hook that could have interrupted it.
Fix the delivery chain: the C-side notification now marks a pending
sigint dispatch and wakes all threads (not just the io thread), and the
scheduler lets an idle thread take over the (free) event loop while a
sigint dispatch is pending, or while the io thread is parked in a
gc-safe foreign region. The julia-side listener clears the pending flag
once the notification reaches it.
With this (plus the LinearAlgebra-side cancellation hooks), ^C during an
interactive A * B on a patched OpenBLAS returns to the prompt in under
two seconds instead of waiting out the multiplication.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012nCkyKUguncLLJrH9K5o7m