common: make no-task Waiter futex parking cancelable - #569
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review. 📝 WalkthroughWalkthroughChanges
ChangesFutex wait behavior
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to The change localizes cancellation handling for no-task waiter parking, with no actionable merge-blocking risk remaining based on the supplied evidence. Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The no-task (foreign/pool-thread) `Waiter` park went straight to a futex wait and only ever returned on completion — a `.allow_cancel` wait was silently uncancelable. Cancellation (SIGURG on the worker's bound token) was absorbed as a spurious wakeup and the thread re-parked. Wrap the `.allow_cancel` futex park in a `syscall_cancel.Syscall` region: SIGURG interrupts the futex with EINTR, and `checkCancel` turns a pending cancel into `error.Canceled`. The token is reached through the threadlocal that `Token.enter` binds, so nothing has to be threaded through the Waiter. When no token is bound (a foreign thread with no cancellation source), `begin()` yields a null-token no-op and the park behaves exactly as before, so existing callers are unaffected. `.no_cancel` always takes the plain path. Enables cancellation of blocking-thread parking (sleep/await/futex on a pool worker) for the blocking std.Io direction (issue #567).
99f20a7 to
b16e8bc
Compare
What
Makes the no-task (foreign/pool-thread)
Waiterfutex park respond to cancellation via the SIGURG cancel token, instead of silently absorbing the signal and re-parking.Why
common.Waiter's no-task path went straight to a futex wait and only ever returned on completion — a.allow_cancelwait was effectively uncancelable. A SIGURG sent to a bound worker's token was swallowed as a spurious wakeup and the thread re-parked. This blocks any cancellation of blocking-thread parking (sleep/await/futex on a pool worker), which the blockingstd.Iodirection needs (issue #567).How
waitFutex/timedWaitFutex, under.allow_cancel, now wrap the park in asyscall_cancel.Syscallregion: SIGURG interrupts the futex withEINTR, andcheckCancelturns a pending cancel intoerror.Canceled. The token is reached through the threadlocal thatToken.enterbinds, so nothing has to be threaded through theWaiter.Zero impact on existing code: when no token is bound,
Syscall.begin()yields a null-token no-op and the park is byte-for-byte the old behavior. Cancellation only activates when a bound token is canceled..no_cancelalways takes the plain path.Test
A bare worker thread binds a
Token, parks a never-signaledWaiterwith.allow_cancel; the main threadcancel()s and resends SIGURG until acknowledged — the park returnserror.Canceledin ~0.5ms (would hang without the fix).All tests pass,
zig fmtclean.Note
This is the enabling half. It's a no-op until a token is actually bound on the parking thread — which the follow-up (blocking-task cancellation) does by giving
AnyBlockingTaska token.