Repository navigation
Conversation
Both worked out a new timer's deadline from the time cached before the loop waited, so a timer started from an I/O callback fired early by the length of the wait, and at once if the wait was longer. kqueue (mitchellh#214), io_uring and wasi_poll already count from the current time. Assisted-by: Claude Opus 5.5
endel
added a commit
to endel/quic-zig
that referenced
this pull request
Oct 23, 2026
Carries mitchellh/libxev#255 (epoll counted a timer started from an I/O callback from before the wait, so it fired early) and #256 (with libc linked, every loop clock read on Linux was a clock_gettime syscall). Assisted-by: Claude Opus 5.5
endel
added a commit
to endel/quic-zig
that referenced
this pull request
Oct 23, 2026
libxev now counts a timer started after a wait from the current time (mitchellh/libxev#255, in the quic-zig-2026-10-23 pin). Assisted-by: Claude Opus 5.5
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.
epoll and IOCP work out a new timer's deadline from
cached_now, whichtickupdates before it waits. A timer started from a callback is therefore counted from before the wait: it fires early by however long the wait took, and at once if the wait took longer than the timer.Timer.rundocumentsnext_msas "from now".kqueue had the same bug and was fixed in #214; io_uring (through its
now_outdatedflag) and wasi_poll already count from the current time. libuv, whose cached loop time this follows, also updates it as soon as the poll returns (uv__io_poll_check, right afterepoll_pwait).We hit this in quic-zig, which re-arms a timer from its socket callback. On epoll it has to call
update_now()first, or a deadline set after a long wait wakes the loop straight away.Fix
io_uring's approach: a
now_outdatedflag, set when the wait returns and cleared byupdate_now.timer_nextupdates the time first when the flag is set. That costs at most one clock read per loop iteration, and only in an iteration whose callbacks start a timer (kqueue reads the clock on everytimer_next). As on kqueue and io_uring,now()called after such a timer returns the updated time.Test
A new
TimerTestscase, run on every backend and the dynamic API: a thread notifies anAsyncafter 50 ms, its callback starts a 20 ms timer, and the test checks that the timer took at least 19 ms. The millisecond of slack is for the test's clock (std.Io.Clock.awake) not being the backend's. It is skipped on WASI, which has no threads.Without the epoll change, or with only the line that sets the flag after the wait removed, the test fails on epoll; it passes on io_uring and kqueue.
zig build test, 60 passedzig build -Demit-example -Demit-bench, andzig buildfor every target in the CI matrix, which compiles the IOCP changeIOCP's change mirrors epoll's line for line; its test is left to CI on Windows. CI on
mainfails until #250 moves the workflow to Zig 0.17, so this PR's checks will fail the same way until then.🤖 Generated with Claude Code
https://claude.ai/code/session_015YcSvZdqwMncezgbb64ihg