Skip to content

feat(coding-agent): diagnose when a child holds stdio open past exit#5758

Closed
Mearman wants to merge 1 commit into
earendil-works:mainfrom
Mearman:feat/diagnose-stdio-held-past-exit
Closed

feat(coding-agent): diagnose when a child holds stdio open past exit#5758
Mearman wants to merge 1 commit into
earendil-works:mainfrom
Mearman:feat/diagnose-stdio-held-past-exit

Conversation

@Mearman

@Mearman Mearman commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #5753. When reviewing that PR you noted it doesn't change that we can end up waiting for the actual bash timeout to kick in. That's true and it's the right behaviour — if a detached descendant keeps writing after the shell exits, re-arming the grace is what stops us truncating the tail. But it's invisible: the command reads as a slow hang with nothing to say the process itself had already exited and a held-open pipe is what kept us reading.

This adds an opt-in PI_STDIO_DEBUG=1 that logs, when the wait resolves, how long a process held stdio open past exit, how much it read in that window, and which path released us (clean eof / idle grace / close). Gated exactly like PI_TIMING, off by default, zero overhead when unset, and it only fires when output actually arrived after exit — i.e. the case that can stretch to the timeout, not every backgrounded handle.

Example line:

[stdio] pid 41234 exited but held stdio open for 4920ms past exit (98 chunk(s), 31610B read after exit; resolved via close)

npm run check and ./test.sh both pass. Two tests in test/child-process-stdio-debug.test.ts: one that the line is emitted with the flag on, one that it stays silent with it off.

The earendil-works#5303 fix keeps reading after exit so output written by a detached
descendant isn't truncated, but the trade-off mitsuhiko flagged on earendil-works#5753
stands: a descendant that writes continuously can hold the wait open until
the command's own timeout kills the tree. That reads as a silent hang with
no hint the process had already exited.

Add an opt-in PI_STDIO_DEBUG=1 diagnostic that logs, on resolution, how long
a process held stdio open past exit, how much it read in that window, and
which path released the wait. Gated like PI_TIMING, off by default, and only
fires when output actually arrived after exit (the timeout-relevant case).
@mitsuhiko

Copy link
Copy Markdown
Member

I don't want to add something like this for the moment. Let's cross that line when it comes up :)

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