test(gap): de-flake test_gap_fs_fd_2749 — it raced the libuv threadpool#6400
Merged
proggeramlug merged 1 commit intoJul 14, 2026
Merged
Conversation
The three callback-form fd mutators are dispatched to the libuv threadpool concurrently, so their callbacks fire in completion order, which is not deterministic. The gap harness compares perry against a freshly run node oracle -- and the *oracle itself* is unstable: across 40 runs of `node --experimental-strip-types` this test produced 4 distinct outputs, emitting `fchown closed cb` before `futimes closed cb` on roughly one run in six. Perry is deterministic here (always submission order), so the test red-lit at random on unrelated PRs -- it took out PerryTS#6397, PerryTS#6398 and PerryTS#6399 today, and cost a full bisect before the oracle was suspected. The test is about the error surface (err.code / err.syscall) of each fd mutator, not about libuv's scheduling. Buffer the three callback results and flush them in a fixed order once all three have landed. Every assertion is preserved and the emitted 10 lines are byte-for-byte what they were; only the print order is pinned. After: node emits 1 distinct output across 60 runs, perry 1 across 40, and the two are byte-identical.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe callback-form test now buffers all three fd-mutator results and prints them in a fixed order after every callback has completed, removing output variability caused by callback completion order. ChangesCallback output determinism
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
🚥 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 |
This was referenced Jul 14, 2026
Merged
This was referenced Jul 14, 2026
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.
test_gap_fs_fd_2749is flaky, and it has been silently red-lighting unrelated PRs. It took out #6397, #6398 and #6399 today — each of which had it as their only untriaged failure — and it cost a full bisect before the oracle itself became the suspect.The test races the libuv threadpool
The three callback-form fd mutators are dispatched concurrently:
Those land on the libuv threadpool and their callbacks fire in completion order, which is not deterministic across three different syscalls.
The gap harness compares perry's output against a freshly run node oracle — and the oracle itself is unstable. Measured directly:
node --experimental-strip-types, 40 runsNode emits
fchown closed cbbeforefutimes closed cbon roughly one run in six:Perry is deterministic (always submission order), so it disagrees with the oracle whenever the oracle takes the minority path. That is a coin flip on every PR, and it is why the failure looked like a regression: it correlated with nothing.
The fix
The test is about the error surface (
err.code/err.syscall) of each fd mutator, not about libuv's scheduling. Buffer the three callback results and flush them in a fixed order once all three have landed.Every assertion is preserved, and the emitted 10 lines are byte-for-byte what they were — only the print order is pinned.
Verification
Deliberately left alone
While restructuring I briefly sequenced the promisified forms by calling
main()from the last callback, and that surfaced a separate, real perry bug: awaiting apromisify(fs.ftruncate)rejection from inside an fs callback yieldsundefined undefinedinstead ofEBADF ftruncate. That is not this PR's business — filing it separately with a repro rather than folding an unrelated runtime bug into a test de-flake.main()stays at top level here, exactly as before.Summary by CodeRabbit