Ssh duplicates FILENO_STDOUT and FILENO_STDERR, thus there are two descriptors for each of those files. When the remote program closes its stdout or stderr, the remote sshd sends the appropriate message to the local ssh which responds by closing the duplicate descriptor, but the original descriptor remains open. A program reading from ssh's stdout (or stderr) cannot tell that the remote program has closed the file. This is what should happen: $ sh -c 'exec cat >&- 2>&-; sleep 5' | { read s || echo eof; } eof [then 5 second pause] This is what happens using ssh: $ ssh localhost 'exec >&- 2>&-; sleep 5' | { read s || echo eof; } [5 second pause] eof
Created attachment 3073 [details] transfer stdout to channel This transfers ownership of stdout to the session channel, clobbering the original STDOUT_FILENO with /dev/null to ensure that nothing writes to it after any subsequent fds are opened, since they could be allocated fd=1.
Created attachment 3074 [details] attempt 2 - delay clobbering of stdout until after LocalCommand Previous patch was incorrect - LocalCommand may write to stdout, so delay clobbering STDOUT_FILENO until it has completed.
Hang on - the patch isn't committed yet!
Patch has been committed and will be in openssh-7.7
Close all resolved bugs after release of OpenSSH 7.7.