Repository navigation
fix(server): keep a stdin error handler after cancelling a run - #94
Merged
JacobLinCool merged 2 commits intoOct 8, 2026
Merged
Conversation
ServerRunner's cleanup for the runtime preparation stage, native runs and native interactive sessions removed the child stdin `error` listener. When a run is cancelled or hits its wall deadline while the parent is still writing a large request (for example the ~15 MB CPython runtime request), the child is SIGKILLed, the pending write fails with EPIPE, and with no listener left the error is emitted unhandled and crashes the host process with "Uncaught Error: write EPIPE". Swap the listener for a no-op instead of dropping it, mirroring the existing late child `error` handling. ServerCompiler and the Go stage already keep their stdin error listeners for the child's lifetime. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # CHANGELOG.md
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.
Why
ServerRunnerremoves the child stdinerrorlistener in its cleanup for three paths: the runtime preparation stage, native runs and native interactive sessions.A run can be cancelled, or hit its wall deadline, while the parent is still writing a large request to the child's stdin. The ~15 MB CPython runtime request is one example. When that happens:
Uncaught Error: write EPIPE.A downstream judge (NOJV) hit this under load, when a Python checker run was cancelled at a request deadline. It currently carries a pnpm patch for it.
Change
errorlistener for a no-op instead of removing it:child.stdin.off("error", onStdinError).on("error", () => undefined).errorevents.closeevent does not wait for stdin, so this also covers late errors after a normal settle.ServerCompilerand the Go stage already keep their stdin error listeners for the child's whole lifetime, so they need no change.CHANGELOG.md: entry underUnreleased. This may conflict trivially with feat(runtime): allow Python interactors in interact #93, which adds the same heading.Verification
server-runner-preparation.test.ts, one case per site (preparation, run, interaction): cancel, then emit EPIPE on the child's stdin. All 3 fail onmainwith'Error: write EPIPE' was thrownand pass with the fix.mainthe host gets an uncaughtError: write EPIPE; with the fix it passes on 3 of 3 runs.pnpm run typecheck,pnpm run lint,pnpm test(959 passed, 9 skipped) andpnpm run buildall pass.🤖 Generated with Claude Code