Skip to content

fix(runtime): deliver JS process stdout/stderr to a redirected fd (pipe/file) - #1967

Open
abcxff wants to merge 1 commit into
stack/fix-runtime-a-blocking-wasm-pipe-read-waits-for-its-writer-instead-of-failing-at-maxblockingreadms-zxsvyrlkfrom
stack/fix-runtime-deliver-js-process-stdout-stderr-to-a-redirected-fd-pipe-file-rsnpzpss
Open

fix(runtime): deliver JS process stdout/stderr to a redirected fd (pipe/file)#1967
abcxff wants to merge 1 commit into
stack/fix-runtime-a-blocking-wasm-pipe-read-waits-for-its-writer-instead-of-failing-at-maxblockingreadms-zxsvyrlkfrom
stack/fix-runtime-deliver-js-process-stdout-stderr-to-a-redirected-fd-pipe-file-rsnpzpss

Conversation

@abcxff

@abcxff abcxff commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Guest process.stdout/process.stderr (and console.log/error) wrote via the _log/_error bridge globals, which append to the process's captured output and bypass kernel fd 1/2. So any redirection was silently dropped: 'node -e ... | cat' produced empty output (wc -c saw 0 bytes) and 'node -e ... > file' wrote nothing, while fs.writeSync(1, ...) — which goes through the kernel fd — worked. Confirmed pre-existing on 0.2.20-rc.1.

Route _stdout/_stderr through the existing _kernelStdioWriteRaw bridge (__kernel_stdio_write -> write_process_stdout/stderr on kernel fd 1/2), the same path WASM stages use, so redirection and pipes are honored. Falls back to _log/_error only when the kernel bridge is unavailable (e.g. browser). Top-level captured output is unchanged (the sidecar drains fd 1).

Verified: process.stdout|cat, console.log|cat, node|wc -c (6 bytes), node>file, console.error 2>&1|cat all deliver output; top-level node output and the #1959 pipelines are unaffected. Note: the symmetric stdin-stream gap (process.stdin does not emit 'data' from a piped fd 0, though fs.readSync(0) works) is a separate follow-up.

…pe/file)

Guest process.stdout/process.stderr (and console.log/error) wrote via the _log/_error bridge globals, which append to the process's *captured* output and bypass kernel fd 1/2. So any redirection was silently dropped: 'node -e ... | cat' produced empty output (wc -c saw 0 bytes) and 'node -e ... > file' wrote nothing, while fs.writeSync(1, ...) — which goes through the kernel fd — worked. Confirmed pre-existing on 0.2.20-rc.1.

Route _stdout/_stderr through the existing _kernelStdioWriteRaw bridge (__kernel_stdio_write -> write_process_stdout/stderr on kernel fd 1/2), the same path WASM stages use, so redirection and pipes are honored. Falls back to _log/_error only when the kernel bridge is unavailable (e.g. browser). Top-level captured output is unchanged (the sidecar drains fd 1).

Verified: process.stdout|cat, console.log|cat, node|wc -c (6 bytes), node>file, console.error 2>&1|cat all deliver output; top-level node output and the #1959 pipelines are unaffected. Note: the symmetric stdin-stream gap (process.stdin does not emit 'data' from a piped fd 0, though fs.readSync(0) works) is a separate follow-up.
@abcxff

abcxff commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator Author

Stack for rivet-dev/agentos

Get stack: forklift get 1967
Push local edits: forklift submit
Merge when ready: forklift merge 1967

change rsnpzpss

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