fix(test): remove two CI flakes — EPIPE on early-exit stdin, and an over-tight async watchdog [DEV-150, DEV-151]#74
Merged
Conversation
`zip_profile_rejects_standard_input_as_usage` intermittently failed (observed on
`main` run 30050968242, passing on the portable profile and failing on the native
one in the same job). The product behaviour is correct: `oxarchive package
validate -` refuses `-` as a usage error and exits 2 *without* reading stdin,
closing the pipe. The `run_stdin` helper then raced that exit — `write_all` of the
JAR body returns `BrokenPipe` (EPIPE) whenever the child exits before the bytes
land in the pipe buffer, and `.expect("write stdin")` turned that into a panic.
Treat `BrokenPipe` as an expected outcome of feeding a process that may reject its
arguments without consuming input; every other write error still panics. Stdin is
scoped so it is closed before `wait_with_output`, so children that *do* read stdin
(e.g. `deb_validates_from_standard_input`) still see EOF.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
P4suta
enabled auto-merge (squash)
July 23, 2026 23:22
…[DEV-151]
`async_xz_never_deadlocks_under_slow_source` (added by DEV-124) aborted on the
`big-endian (s390x, qemu)` and `test (macos-latest)` jobs:
watchdog: `async_xz_never_deadlocks_under_slow_source` did not complete
within 30s; aborting the deadlocked test
That was not a deadlock — it was the watchdog mistaking *slowness* for one. Driving
the reader one byte per poll for 50 iterations honestly exceeds 30s on an emulated
s390x (10-50x slower than a native host) and on a loaded macOS runner, so the guard
meant to kill flakes became a flake itself.
Detection determinism comes from the park/unpark driver, not the repeat count: the
executor has nothing else to poll, so a lost wakeup parks forever on the very first
iteration. Trim the loop to 8 repeats (still exercising the NeedInput/Output
interleaving) and raise the budget to 240s via a documented `WATCHDOG_BUDGET`
constant — a real hang still aborts fast and attributably, well inside the job's
`timeout-minutes`, while honest slowness no longer trips it. The suite now runs in
0.30s natively.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Two independent test-harness flakes that were turning
mainand PR runs red. Both are test bugs, not product bugs. Linear: DEV-150, DEV-151.1. EPIPE when a CLI rejects stdin early (DEV-150)
Turned
mainred on6d51600(run 30050968242) — and reproduced on re-run.zip_profile_rejects_standard_input_as_usageasserts thatoxarchive package validate -refuses-as a usage error (exit 2). That behaviour is correct: the CLI exits immediately without reading stdin, closing the pipe. Therun_stdinhelper raced that exit —write_all(jar).expect("write stdin")returnsBrokenPipe(EPIPE) whenever the child exits before the bytes land in the pipe buffer, so.expectpanicked based purely on scheduling.Fix: treat
BrokenPipeas an expected outcome of feeding a process that may reject its arguments without consuming input; every other write error still panics. Stdin is scoped closed beforewait_with_output, so children that do read stdin (deb_validates_from_standard_input) still see EOF. The test's assertions are unchanged.2. Async deadlock watchdog too tight for emulated/loaded runners (DEV-151)
Failed
big-endian (s390x, qemu)andtest (macos-latest)on this PR's first run:Not a deadlock — the watchdog (added with DEV-124) mistook slowness for one. Driving the reader one byte per poll for 50 iterations honestly exceeds 30s on an emulated s390x and a loaded macOS runner, so the guard meant to kill flakes became one.
Fix: detection determinism comes from the park/unpark driver, not the repeat count — the executor has nothing else to poll, so a lost wakeup parks forever on the first iteration. Trim the loop to 8 repeats and raise the budget to 240s via a documented
WATCHDOG_BUDGET. A real hang still aborts fast and attributably, well inside the job'stimeout-minutes; honest slowness no longer trips it.Verification
package_cli→ 9 passed; the previously flaky stdin test repeated 12/12 green.async_stream_v2→ 6 passed, suite now 0.30s natively (was dominated by the 50-iteration loop).🤖 Generated with Claude Code