fix(cli): read stdin lazily so open pipes don't hang the CLI - #1330
Open
l2ysho wants to merge 1 commit into
Open
fix(cli): read stdin lazily so open pipes don't hang the CLI#1330l2ysho wants to merge 1 commit into
l2ysho wants to merge 1 commit into
Conversation
Every command paid for stdin: `_shared.ts` did `await readStdin()` at module scope, so `apify --version` blocked on a stream it never reads. With a named pipe (no wait deadline, unlike the socket a spawned child gets) the read never ended and the command never even ran. Read stdin only when a command asks for it — a `-` arg/flag, `apify run` without `--input`, `push-data`/`push-items` without an item. Result is memoized, since stdin can only be drained once. Confirmations previously keyed off `hasData`, which the eager read flipped to false once stdin was drained. Without that read the flag stays true, so `apify <confirm-cmd> < /dev/null` would try to prompt on a non-TTY; gate on `isTTY` instead. Commands that genuinely consume stdin still wait for the writer to close, same as `cat`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
l2ysho
marked this pull request as ready for review
August 14, 2026 11:02
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.
Note
TL;DR — The CLI read stdin at startup for every command, so a pipe that stays open hung it forever. Now it only reads stdin when a command actually wants it.
Closes #1206.
_shared.tsread stdin at module scope (export const cachedStdinInput = await readStdin()), so every command blocked on stdin whether or not it uses it. #1294 fixed the socket case (a spawned child'sstdio: 'pipe'), but a named pipe has no wait deadline — the read never ended and the command never even ran, so 1.8.0 still hangs with no output at all:Read stdin only where it's asked for: a
-arg/flag,apify runwithout--input,push-data/push-itemswithout an item arg.readStdin()memoizes, since stdin can only be drained once.Confirmations keyed off
hasData, which the eager read flipped to false after draining. Without that read it stays true, soapify <confirm-cmd> < /dev/nullwould try to prompt on a non-TTY — gated onisTTYinstead.Unchanged by design: commands that genuinely consume stdin still wait for the writer to close, same as
cat.Verification
New e2e case: real FIFO via
mkfifo, openedr+so it never EOFs (skipped on Windows). Fails on the pre-fix build (60s timeout), passes after.stdio: 'pipe'(socket, #1294's case)pnpm run test:localgreen (2 pre-existing python-fixture failures, fail on master too — local python env). No dependency or install-size change.🤖 Generated with Claude Code