WIP: Investigate PTY-based TeeStream for interleaving (#313) #370
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.
Summary
This PR reintroduces the PTY-based
TeeStreamclass (which was replaced byTailPipein May 2024) to investigate whether it can help with stdout/stderr interleaving for #313.Findings
The buffering problem
When capturing output through duct, interleaving is lost even when the child process outputs in order:
What we tested
Key insight: The child's buffering isn't the problem - duct's architecture is.
Why TailPipe doesn't interleave
Popen(stdout=file1, stderr=file2)- streams separated at kernel levelWhy TeeStream (PTY) also doesn't interleave (in current form)
We reintroduced TeeStream with PTY-based capture, but with two separate PTYs (one per stream), interleaving is still lost.
What DOES work
When both stdout AND stderr go to the same PTY slave fd:
This gives perfect interleaving because the kernel merges both streams in arrival order.
Recommendation for #313
For a
--capture-outputs=combinedorannotatedmode:[stdout]/[stderr]prefixes (though with shared PTY, we lose stream distinction)If stream distinction is needed with interleaving, would need the pipe+select approach:
subprocess.PIPEfor both streamsselect.select()to multiplex reads in a single threadTest script
interleave.pyis included for reproducing the behavior.🤖 Generated with Claude Code