Skip to content

Drain the :consume stderr tail when the child exits - #19

Closed
woohp wants to merge 1 commit into
nyo16:masterfrom
woohp:fix-stderr-drain-on-exit
Closed

woohp wants to merge 1 commit into
nyo16:masterfrom
woohp:fix-stderr-drain-on-exit

Conversation

@woohp

@woohp woohp commented Sep 25, 2026 •

Copy link
Copy Markdown

In :consume stderr mode, the tail can miss the child's last writes when the exit status arrives before the stderr readiness event.

finish_exit/2 serves parked stdout/stderr readers from the pipe (the comment there explains why: the exit status can arrive over the UDS while output is still sitting in the pipe), but the :consume drain is only driven by select events, so nothing drains it at exit. If the UDS exit message wins the race, stderr_tail/1 called right after await_exit/1 returns a short or empty tail. That includes run/2 with stderr: :capture, whose comment says the tail is complete once the process has exited. stderr_tail_test.exs works around it with wait_until_drained/2 ("avoids racing the select-driven consumer against the OS process exit notification").

Fix: also call maybe_consume_stderr/1 in finish_exit/2. The child's write ends are closed by then, so the drain reads the remaining bytes and stops at :eof (or :eagain if a grandchild still holds the pipe open). The :consume_stderr_more handler already treats a drain after exit as a no-op

finish_exit/2 served parked stdout/stderr readers from the pipe but not the
select-driven :consume drain. When the exit status arrived before the stderr
readiness event, stderr_tail/1 right after await_exit/1, and run/2 with
stderr: :capture, missed the child's last writes: about 1 run in 2,000 on an
ubuntu-latest runner under concurrent load.

The regression test runs 2,000 concurrent children through both entry
points; it failed on ubuntu-latest before this change and passes on every
CI job after it.
@woohp woohp closed this Sep 25, 2026
@woohp
woohp deleted the fix-stderr-drain-on-exit branch September 25, 2026 22:49
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