Skip to content

Handle a closed stdout like HotSpot - #10

Merged
Project516 merged 1 commit into
masterfrom
p516/epipe
Nov 1, 2026
Merged

Project516 merged 1 commit into
masterfrom
p516/epipe

Conversation

@Project516

Copy link
Copy Markdown
Owner

java-web Main | head -1 crashed with node's "Unhandled 'error' event" and exit code 1 once head closed the pipe. HotSpot keeps running: System.out sets its error flag (checkError() is true), a raw FileOutputStream on fd 1 throws IOException: Broken pipe, and the exit code is the program's.

The Node entry now listens for errors on its stdout and stderr and, once one fails, throws IOException("Broken pipe") from later writes. Node never marks its stdio streams destroyed and reports each failed write on the next event loop turn, so writes made before that turn are dropped silently rather than failing; the program still runs to the end, as on HotSpot.

A new test closes the reader after the first chunk and compares stderr and the exit code with HotSpot; it fails without this change.

Verified: the new test (4 runs), pnpm typecheck.

@coderabbitai

coderabbitai Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Caution

Review failed

The pull request is closed.

Summary

Summary by CodeRabbit

  • Bug Fixes
    • Writes to standard output or error now report a broken pipe after the receiving process closes the stream, rather than failing unpredictably.
    • Direct writes to standard output now produce a Java IOException with a “Broken pipe” message when the stream is closed.
  • Tests
    • Added coverage comparing closed-pipe behavior with HotSpot Java, including error output and process exit status.

The Node runtime now routes default stdout and stderr through writers that track stream errors and raise Java IOException("Broken pipe") on later writes. A Java test program and spawned-process test compare this behavior with HotSpot after stdout closes.

Changes: Broken-pipe handling

Layer / File(s) Summary
Default output stream error handling
src/node.ts
Default host output writers track stream errors. Later writes raise PendingThrow for java/io/IOException with the message "Broken pipe". Explicit callbacks remain in use when supplied.
Broken-pipe behavior test
test/pipe/Pipe.java, test/programs.test.ts
The Pipe program writes to stdout and reports stream and raw-write errors. The spawned-process test closes stdout after its first data event and compares stderr and exit codes for java-web and HotSpot.

Estimated code review effort: 2 (Simple) | ~12 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant programs.test
  participant Pipe
  participant java-web
  participant stdout
  programs.test->>java-web: Spawn Pipe with piped stdout and stderr
  Pipe->>stdout: Write output
  programs.test->>stdout: Close after first data event
  stdout-->>java-web: Emit stream error
  Pipe->>java-web: Attempt a later stdout write
  java-web-->>Pipe: Raise IOException with "Broken pipe"
  programs.test->>programs.test: Compare stderr and exit code with HotSpot
Loading

Possibly related PRs

  • Project516/java-web#4: Adds the Node CLI and runNode entry points whose default stdout and stderr behavior this change updates.
Merge Risk: Low · up to 1339d

Piping java-web output into a reader that closes early now behaves like HotSpot once the stream failure has been reported. A program that finishes its writes before Node reports the failure can still complete without the IOException on raw stdout writes. The impact is narrow and has a safe fallback, so it is acceptable to merge with awareness of the gap.

- [ ] Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

Share

A rabbit heard the stdout stream go pop,
Then watched the writer pause its hop.
“Broken pipe,” the Java notes declare,
While HotSpot joins the test with care.
The rabbit thumps and bounds away.

@project516-review-bot project516-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR adds handling for closed stdout/stderr pipes to match HotSpot behavior: when the reader closes the pipe (e.g., java-web Main | head -1), writes now throw IOException("Broken pipe") instead of crashing Node with an unhandled error event. A hostOut wrapper installs an error listener on process.stdout/process.stderr; once an error occurs, subsequent writes throw a PendingThrow that the JVM converts to a Java IOException. A new test (Pipe.java) writes many lines, sleeps to let the event loop process the pipe closure, then verifies System.out.checkError() and raw FileOutputStream behavior match HotSpot. The test passes and typecheck is clean.


review-bot, model nvidia/nemotron-3-ultra-550b-a55b:free, verdict approve

@Project516
Project516 merged commit b3f9c7c into master Nov 1, 2026
5 of 6 checks passed
@Project516
Project516 deleted the p516/epipe branch November 1, 2026 21:52
@Project516 Project516 mentioned this pull request Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant