On 12/10/17 12:54, Clark Wang wrote:> How did you hit the problem? "ssh host echo hello | cat" works fine > for me.That's because ssh exited, not because of EOF. Consider the following: ?? ssh localhost 'exec cat > /dev/null' | { read l; echo ${l:-EOF}; } One should see "EOF" immediately (for values of immediate that include startup latency), but that's not what happens. I did have a better example.? When ssh was run with debug output, it showed ssh drain and close output when the remote end closed it's output.? Owing to ssh having two copies of the output descriptor, the downstream program did not see that EOF (it's not EOF until both file descriptors are closed.)? Now, irritatingly, I can't reproduce that.? Now, the remote program closes its output, the sshd parent closes its end of that pipe, but ssh smugly sits there, keeping output (both copies) open until the remote program exits.? Clearly there is more going on that just two descriptors to the same output pipe. It's wrong; ssh should not absorb EOF.
On Fri, Oct 13, 2017 at 3:24 PM, David Newall <openssh at davidnewall.com> wrote:> On 12/10/17 12:54, Clark Wang wrote: > >> How did you hit the problem? "ssh host echo hello | cat" works fine for >> me. >> > > That's because ssh exited, not because of EOF. > > Consider the following: > > ssh localhost 'exec cat > /dev/null' | { read l; echo ${l:-EOF}; } > > One should see "EOF" immediately (for values of immediate that include > startup latency), but that's not what happens. >The ssh is still alive since the remote cat is waiting for input so the read would not see EOF. Did you actually mean 'exec cat < /dev/null'?
On 13/10/17 18:40, Clark Wang wrote:> On Fri, Oct 13, 2017 at 3:24 PM, David Newall <openssh at davidnewall.com > <mailto:openssh at davidnewall.com>> wrote: > > > ?? ssh localhost 'exec cat > /dev/null' | { read l; echo ${l:-EOF}; } > > One should see "EOF" immediately (for values of immediate that > include startup latency), but that's not what happens. > > > The ssh is still alive since the remote cat is waiting for input so > the read would not see EOF. Did you actually mean 'exec cat < /dev/null'? >The ssh is still alive since the remote cat is waiting for input. That has zero relevance to EOF.? If you still don't get it, please replace "ssh localhost" with "sh -c" and see what should happen.
> I did have a better example.I do have a better example. ? ssh localhost 'exec cat > /dev/null 2>&1' | { read l; echo ${l:-EOF}; } (Bonus points for seeing the irony.) This should immediately print EOF.? It doesn't, because the duplicate file descriptor on stdout prevents pipe closure until ssh exits. Simply removing dup(), that is, saying "out = STDOUT_FILENO", results in correct behavior.? I think it's the right change.? I'll go further and suggest that the same change should be made to err.? I would suggest it should also be made to in, but that breaks tcsetattr on exit.
On 10/13/2017 7:21 AM, David Newall wrote:>> I did have a better example. > > I do have a better example. > > ? ssh localhost 'exec cat > /dev/null 2>&1' | { read l; echo ${l:-EOF}; } > > (Bonus points for seeing the irony.) > > This should immediately print EOF.No. Because cat is reading from stdin which is from the ssh command line that is still open so cat is stil running. If you type in a few lines, then hit Ctrl-D It does type EOF To make it clear what is going on, changing /dev/null to /tmp/xxx ssh localhost 'exec cat > /tmp/out 2>&1' | { read l; echo ${l:-EOF}; } type in a few lines then Ctrl-D will type EOF ssh localhost 'exec echo XYZ | cat > /tmp/xxx 2>&1' | { read l; echo ${l:-EOF}; } will immediately type EOF and /tmp/xxx will have XYZ ssh localhost 'exec echo XYZ | cat > /etc/nofilehere 2>&1' | { read l; echo ${l:-EOF}; } outputs bash: /etc/nofilehere: Permission denied EOF becase of the redirect of cat's stderr to stdout It doesn't, because the duplicate file descriptor on stdout prevents pipe closure until ssh exits.> > Simply removing dup(), that is, saying "out = STDOUT_FILENO", results in correct behavior.? I think it's the right change.? I'll go further and suggest that the same change should be made to err.? I > would suggest it should also be made to in, but that breaks tcsetattr on exit. > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev-- Douglas E. Engert <DEEngert at gmail.com>