wasi-shims: re-arm the timer pollable's sleep; chunk below the setTimeout ceiling - #78
Merged
Conversation
…eout ceiling Pollable.timer cached its wake promise forever (armed ??= with no reset). ready() consults the clock, so any EARLY-firing sleep left the cached promise permanently settled while ready() stayed false — and block()/poll()'s re-check loops (await an already-settled promise, re-check, repeat) degenerate to a hot microtask spin that starves the event loop: the livelock class the parking kernel exists to kill. The severe trigger is the engine's setTimeout ceiling: delays above 2^31-1 ms are clamped to ~0 (node/Deno warn and fire at 1 ms), so any deadline past ~24.8 days — far-future timeouts, u64 sentinels — spun hot for its whole duration. Ordinary timer slop (early by a tick) caused the same spin briefly. Fix: one in-flight sleep shared by concurrent waiters, re-armed after every settle with the delta recomputed, each sleep capped at the ceiling (TIMER_CHUNK_MAX_MS) — far deadlines sleep in chunks and re-check the clock at each chunk end. Pins (both fail-on-pre-fix, verified by stash/unstash): a frozen-clock early fire must yield a fresh PENDING promise from the next wait(); a +60-day deadline's wait is still parked 30 ms in (pre-fix the clamp settled it at ~1 ms). sanitizeOps off for exactly these two: the re-armed sleeps outlive the tests by design (nothing in the WIT surface cancels a timer). Gates: test-wasi-shims 52/0 (+2), websocket-conformance 55/55 at baseline wall time.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Review finding on #71:
Pollable.timercached its wake promise forever (armed ??=, never reset).ready()consults the clock, so an early-firing sleep left the cached promise permanently settled whileready()stayed false —block()/poll()'s re-check loops then await an already-settled promise in a tight cycle: a hot microtask spin that starves the event loop, i.e. the livelock class the parking kernel exists to kill.Severe trigger: the engine setTimeout ceiling — delays > 2^31−1 ms clamp to ~0 (node/Deno warn, fire at 1 ms; verified empirically) — so any deadline past ~24.8 days (far-future timeouts, u64 sentinels) spun hot for its whole duration. Ordinary timer slop (early by a tick) caused the same spin briefly.
Fix: one in-flight sleep shared by concurrent waiters (promise-swap contract unchanged), re-armed after every settle with the delta recomputed; each sleep capped at
TIMER_CHUNK_MAX_MS(2^31−1) so far deadlines sleep in ceiling-sized chunks, re-checking the clock at each chunk end.Pins (both fail-on-pre-fix, verified via stash/unstash): frozen-clock early fire → next
wait()must be a fresh pending promise; +60-day deadline → wait still parked 30 ms in (pre-fix: settled at ~1 ms).sanitizeOps: falseon exactly these two — the re-armed sleeps outlive the tests by design (the WIT surface has no timer cancel).Gates:
just test-wasi-shims52/0 (+2 new),just websocket-conformance55/55 at baseline wall time (14.4 s).