fix copy_buf_to_buf: flush partial lines when source pipe closes#1
Merged
HoratiuVultur merged 1 commit intomasterfrom Apr 9, 2026
Merged
Conversation
copy_buf_to_buf() only forwards data to the output buffer when it
finds a complete line (terminated by '\n'), the line exceeds
LINE_SIZE_MAX, or a 1-second timeout expires. When a child process
writes output without a trailing newline and exits immediately, the
main loop can terminate before any of these conditions are met:
1. Child writes partial line to stdout and exits.
2. SIGCHLD sets child_running = 0.
3. copy_to_buffer() reads pipe data and gets EOF, closing the fd.
4. copy_buf_to_buf() finds no '\n', line isn't too long, and
line_timeout() returns false (< 1s elapsed).
5. Data stays in the read buffer, unformatted.
6. Next iteration: all fds closed, cnt == 0, loop breaks.
7. EXIT message emitted STDOUT data silently lost.
This was discovered via easyframes (ef), which prints an error
without a trailing newline:
po("ERROR: Frame stack size is too big");
When ef was invoked with 29+ tx clauses through er, the error was
lost and the test framework only saw "Exit 255" with no explanation.
Fix this by checking whether the source pipe has been closed
(from->fd == -1) before falling through to line_timeout(). When
the pipe is closed, any remaining data is the final output from
the child and should be flushed immediately as a normal ER-L line.
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.
Flush remaining output data when a child process's pipe is closed, even if the data doesn't end with a newline.
copy_buf_to_buf()only forwards data to the output buffer when one of three conditions is met:\n)LINE_SIZE_MAXline_timeout()expiresWhen a child process writes output without a trailing newline and exits immediately, the main loop terminates before any of these conditions are met:
child_running = 0copy_to_buffer()reads remaining pipe data and gets EOF, closing the fdcopy_buf_to_buf()finds no\n, line isn't too long, andline_timeout()returns false (< 1s elapsed)cnt == 0, loop breaksThis was discovered via easyframes (ef), which prints an error without a trailing newline:
When ef was invoked with 29+ tx clauses through er, the error was lost and the test framework only saw "Exit 255" with no explanation, which made debugging harder.
Fix
Check whether the source pipe has been closed (
from->fd == -1) before falling through toline_timeout(). When the pipe is closed, any remaining data is the final output from the child and should be flushed immediately as a normalER-Lline:This is placed before the
line_timeoutcheck since it is a more specific condition. There is no point waiting for a timeout on a pipe that will never produce more data.