SIGN IN SIGN UP

ssh/tailssh: hold CHANNEL_EOF until both output streams drain

The previous commit sent CHANNEL_EOF from the stdout copier as soon as
stdout hit EOF. With the process exited and the send window exhausted by
a slow client, the stderr copier could still be draining its backlog;
x/crypto/ssh fails every write after EOF (WriteExtended checks sentEOF),
so the tail of stderr was silently dropped.

Send CloseWrite from run() itself, after cmd.Wait, exit-status and both
output copiers have finished. Wire order is unchanged: exit-status,
remaining output, EOF, CHANNEL_CLOSE.

The test withholds stderr window credit until the process has exited
server-side, then releases it and checks the final bytes arrived. It
also pins the harness login shell to /bin/sh; fish forks -c commands and
stays resident, changing pipe fd ownership under test.

Updates #18256

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
K
Kristoffer Dalby committed
dd426dbb51b5e625096b7afa09b62da189550df8
Parent: 92f4300
Committed by Kristoffer Dalby <kristoffer@dalby.cc> on 7/30/2026, 8:18:00 AM