Skip to content

fix(guest): prevent out-of-order stdout in PTY mode - #62

Merged
DorianZheng merged 1 commit into
mainfrom
fix/pty-stdout-ordering
Jan 2, 2026
Merged

DorianZheng merged 1 commit into
mainfrom
fix/pty-stdout-ordering

Conversation

@DorianZheng

Copy link
Copy Markdown
Member

Summary

  • Fix race condition in PTY mode where two readers competed for the same PTY master FD
  • In PTY mode, stderr is now merged into stdout (single reader), following kata-containers pattern
  • Non-PTY mode unchanged - still has separate stdout/stderr pipes

Problem

In PTY mode, the code incorrectly created two separate readers from the same PTY master:

let stdout_fd = dup(master.as_raw_fd())  // reader #1
let stderr_fd = dup(master.as_raw_fd())  // reader #2 - SAME underlying FD!

Both readers had their own BufReader, causing:

  • Race conditions when reading
  • Out-of-order output (chunks captured by "wrong" reader)
  • Data appearing on stderr when it should be on stdout

Solution

Follow kata-containers pattern:

  • Only ONE reader from PTY master → stdout
  • Pass None for stderr in PTY mode
  • All terminal output flows through single stdout stream

Changes

File Change
exec_handle.rs new() accepts Option<OwnedFd> for stderr
executor.rs PTY: pass None, non-PTY: Some(stderr)
command.rs Same pattern, fix reconcile_pty_fds

Test Plan

  • Run interactivebox_example.py and verify output ordering
  • Test commands mixing stdout/stderr: ls /nonexistent 2>&1

@DorianZheng
DorianZheng force-pushed the fix/pty-stdout-ordering branch 3 times, most recently from 7f21473 to f4e2815 Compare January 2, 2026 02:11
In PTY mode, stdout and stderr are merged at the PTY level. The previous
implementation incorrectly created two separate readers from the same PTY
master FD, causing a race condition where data could be captured by the
"wrong" reader, resulting in out-of-order output.

This fix follows the kata-containers pattern:
- Only create ONE reader from the PTY master (stdout)
- Pass stderr as None in PTY mode
- Non-PTY mode remains unchanged with separate pipes

Changes:
- exec_handle.rs: Change new() to accept Option<OwnedFd> for stderr
- executor.rs: PTY mode passes None, non-PTY wraps stderr in Some()
- command.rs: Same pattern, also fix reconcile_pty_fds to return only stdin/stdout
@DorianZheng
DorianZheng force-pushed the fix/pty-stdout-ordering branch from f4e2815 to 29fddc6 Compare January 2, 2026 02:14
@DorianZheng
DorianZheng merged commit 255d167 into main Jan 2, 2026
4 checks passed
@DorianZheng
DorianZheng deleted the fix/pty-stdout-ordering branch January 2, 2026 03: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