Skip to content

fix(io): write held stdout before a JS File read - #1893

Closed
MattCozendey wants to merge 1 commit into
bendlang:mainfrom
MattCozendey:fix/js-read-sync
Closed

MattCozendey wants to merge 1 commit into
bendlang:mainfrom
MattCozendey:fix/js-read-sync

Conversation

@MattCozendey

Copy link
Copy Markdown
Contributor

Bug: on JS, IO.print holds stdout when it is a pipe. File.read* blocks in readvSync without writing it out first, so a program that prints and then waits for a reply deadlocks. C writes it out before it waits (io_sync before select).

Repro: { printf 'a\n'; sleep 3; printf 'b\n'; } | node prog.js, where prog.js echoes each File.read_line of /dev/stdin. JS prints a after 3 s; native prints it at once.

Fix: io_sync() at the top of file_read_with, as file_write.js does. Only bend2/effs/file_read.js (+2 lines) and one test in tests/io/ change.

Cost: a loop that prints between reads now writes on each read, as C does.

Tested: new tests/io/file_read_stdout_order: on main, the interpreter, Bun and Node print two one three, and native passes; with the fix, all four pass. Nearby tests/io file and stdout tests pass. Linux (WSL2), Bun + Node. Not tested: macOS, the cluster gates.

🤖 Generated with Claude Code

On JS, IO.print holds stdout off a terminal, and File.read* blocked in
readvSync with the text still held, so a program that prints and then
waits for a reply deadlocked. C already writes it before it waits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nicolas-abril

Copy link
Copy Markdown
Collaborator

Closing in favour of #1899, which fixes this in the loop instead of in File.read alone. The JS File and Process effects now park themselves, so io_wait flushes held stdout before any of them blocks, as C does through io_work. This also covers File.open and Process.run, which had the same deadlock. Your test file_read_stdout_order is kept in #1899. Thanks for finding this!

nicolas-abril added a commit that referenced this pull request Oct 27, 2026
On JS, File.open/read*/size/write* and Process.run ran synchronously
inside the effect, so the loop never reached io_wait and never wrote
what IO.print holds before blocking: a program that prints and then
reads from a peer waiting for that output deadlocked. C runs these
through io_work, parks the fiber, and flushes in io_wait.

Each of these effects now parks itself with io_park_on, due at once, so
it runs at the next io_wait, after its io_sync, as in C. Other fibers
run before its result, as in C. io_wait skips select when it waits on
no fd with a zero timeout, so parked files need no bun:ffi on node.
File.write's own io_sync goes away.

Supersedes #1893; its test file_read_stdout_order is kept.

Co-authored-by: MattCozendey <MattCozendey@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nicolas-abril added a commit that referenced this pull request Oct 27, 2026
…ut (#1899)

On JS, the File effects and Process.run ran synchronously inside the effect, so the loop never reached io_wait and never wrote what IO.print holds before blocking: a program that prints and then reads from a peer waiting for that output deadlocked. C runs these through io_work, parks the fiber, and flushes in io_wait.

Each of these effects (File.open/open_bytes, read/read_line/read_bytes/read_at, size, write/write_bytes/write_at, Process.run) now parks itself with io_park_on, due at once, so it runs at the next io_wait, after its io_sync, as in C. io_wait skips select when it waits on no fd with a zero timeout, so parked files need no bun:ffi on node. File.write's own io_sync goes away.

Tests: file_read_stdout_order (from #1893), file_read_prompt (from #1895), and file_open_fifo_peer, a FIFO whose writer waits for held stdout, which hangs the JS lane on main.

Co-authored-by: MattCozendey <75740566+MattCozendey@users.noreply.github.com>
Co-authored-by: toprameen <11931132+toprameen@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MattCozendey
MattCozendey deleted the fix/js-read-sync branch October 29, 2026 09:19
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.

2 participants