Fix partial write data loss in TTY stdin relay (#40032)

When the TtyMaster fd is non-blocking, write() can return fewer bytes than
requested (partial write). The existing code only handled the EAGAIN/EWOULDBLOCK
case by buffering into pendingStdin, but silently dropped data on successful
partial writes.

Add handling for 0 < bytesWritten < bytesRead to buffer the unwritten bytes
into pendingStdin, matching the existing retry logic.

Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
This commit is contained in:
Ben Hillis
2026-03-30 14:20:09 -07:00
committed by GitHub
parent 9c978e2b64
commit 103d3dac3b

View File

@@ -315,8 +315,8 @@ void HandleMessageImpl(wsl::shared::SocketChannel& Channel, const WSLC_TTY_RELAY
if (bytesWritten < 0)
{
//
// If writing on stdin's pipe would block, mark the write as pending an continue.
// This is required blocking on the write() could lead to a deadlock if the child process
// If writing on stdin's pipe would block, mark the write as pending and continue.
// This is required because blocking on the write() could lead to a deadlock if the child process
// is blocking trying to write on stderr / stdout while the relay tries to write stdin.
//
@@ -331,6 +331,11 @@ void HandleMessageImpl(wsl::shared::SocketChannel& Channel, const WSLC_TTY_RELAY
break;
}
}
else if (bytesWritten < bytesRead)
{
// Partial write — buffer the remaining bytes for the next iteration.
pendingStdin.assign(buffer.begin() + bytesWritten, buffer.begin() + bytesRead);
}
}
}