I've been using ssh without it duping stdout and stderr, and had no problems.? I think this change should be made to the master source. WHAT IS THE PROBLEM WITH SSH RIGHT NOW? It duplicates FILENO_STDOUT and FILENO_STDERR, thus there are two descriptors for each of these 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 corresponding (duplicate) descriptor, but it ignores the original descriptor, thus that file remains open.? The result of this is that a program reading from ssh's stdout (or stderr) has no way of knowing that the remote program has closed the file. WHY IS THAT BAD? For interactive purposes, I suppose it isn't a problem.? It's true that the remote program can send no further ouput (or error output), but everything proceeds in an otherwise reasonable way.? Where it is a problem is if you want to use ssh in a script.? It's significant when a remote program closes stdout.? It means something.? It means that no more output will be produced, the next program in the pipeline will receive no more input, and should take action for end-of-file.? At present, the next program in the pipeline cannot take action for end-of-file until ssh exits.? The ssh program will not exit until the remote program exits, but, in a scripted situation, it may well be waiting for end-of-file on its input, and thus we have a deadlock: the remote program has closed output and is waiting for input to close; the local program that is next in the pipeline is waiting for its input to close, which will never occur, and thus has no way to signal that it has finished its job.? The program providing input has no way of knowing that the remote program has closed output and thus has no way of knowing that it should close its input. WHAT IMPACT IS THERE FROM NOT DUPLICATING THESE DESCRIPTORS? As far as I can tell, only that ssh's accurately mirrors the remote program's output.? That already happens for all data written to output.? Closing ssh's output (all descriptors) merely completes the picture.? Ssh does not, of itself, use stdout; it has no reason to keep stdout open.? As far as I can tell, the change I am proposing has no deleterious effect. WHAT IS THE EXACT CHANGE? This patch allows a program reading ssh's output to see an EOF from the remote session. Good for scripting. Author: David NewallPatch-Name: scriptable-ssh.patch --- diff -u a/ssh.c b/ssh.c --- a/ssh.c +++ b/ssh.c @@ -1837,11 +1837,11 @@ } else { in = dup(STDIN_FILENO); } - out = dup(STDOUT_FILENO); - err = dup(STDERR_FILENO); + out = STDOUT_FILENO; + err = STDERR_FILENO; - if (in < 0 || out < 0 || err < 0) - fatal("dup() in/out/err failed"); + if (in < 0) + fatal("dup() in failed"); /* enable nonblocking unless tty */ if (!isatty(in)) WHAT CAN I DO TO HELP STEWARD THIS CHANGE INTO THE MASTER SOURCE? What do I need to do? David
Sorry for repeating myself.? It's been pointed out that I need a convincing demonstration.? (I feel I already have given that, but here are all the details, in the one post, including a demonstration.) I've been using ssh without it duping stdout and stderr, and had no problems.? I think this change should be made to the master source. WHAT IS THE PROBLEM WITH SSH RIGHT NOW? It duplicates FILENO_STDOUT and FILENO_STDERR, thus there are two descriptors for each of these 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 corresponding (duplicate) descriptor, but it ignores the original descriptor, thus that file remains open.? The result of this is that a program reading from ssh's stdout (or stderr) has no way of knowing that the remote program has closed the file. WHY IS THAT BAD? For interactive purposes, I suppose it isn't a problem.? It's true that the remote program can send no further ouput (or error output), but everything proceeds in an otherwise reasonable way.? Where it is a problem is if you want to use ssh in a script.? It's significant when a remote program closes stdout.? It means something.? It means that no more output will be produced, the next program in the pipeline will receive no more input, and should take action for end-of-file.? At present, the next program in the pipeline cannot take action for end-of-file until ssh exits.? The ssh program will not exit until the remote program exits, but, in a scripted situation, it may well be waiting for end-of-file on its input, and thus we have a deadlock: the remote program has closed output and is waiting for input to close; the local program that is next in the pipeline is waiting for its input to close, which will never occur, and thus has no way to signal that it has finished its job.? The program providing input has no way of knowing that the remote program has closed output and thus has no way of knowing that it should close its input. WHAT IMPACT IS THERE FROM NOT DUPLICATING THESE DESCRIPTORS? As far as I can tell, only that ssh's accurately mirrors the remote program's output.? That already happens for all data written to output.? Closing ssh's output (all descriptors) merely completes the picture.? Ssh does not, of itself, use stdout; it has no reason to keep stdout open.? As far as I can tell, the change I am proposing has no deleterious effect. PROVE IT! This is what should happen: ? $ sh -c 'exec cat >&- 2>&-; sleep 5' | { read something && echo $something || echo eof; } ? eof ? [then 5 second pause] This is what happens using ssh: ? $ ssh localhost 'exec >&- 2>&-; sleep 5' | { read something && echo $something || echo eof; } ? [5 second pause] ? eof Try for yourself! WHAT IS THE EXACT CHANGE? This patch allows a program reading ssh's output to see an EOF from the remote session. Good for scripting. Author: David NewallPatch-Name: scriptable-ssh.patch --- diff -u a/ssh.c b/ssh.c --- a/ssh.c +++ b/ssh.c @@ -1837,11 +1837,11 @@ } else { in = dup(STDIN_FILENO); } - out = dup(STDOUT_FILENO); - err = dup(STDERR_FILENO); + out = STDOUT_FILENO; + err = STDERR_FILENO; - if (in < 0 || out < 0 || err < 0) - fatal("dup() in/out/err failed"); + if (in < 0) + fatal("dup() in failed"); /* enable nonblocking unless tty */ if (!isatty(in)) WHAT CAN I DO TO HELP STEWARD THIS CHANGE INTO THE MASTER SOURCE? What do I need to do? David
On Fri, 20 Oct 2017, David Newall wrote:> WHAT CAN I DO TO HELP STEWARD THIS CHANGE INTO THE MASTER SOURCE? > What do I need to do?Stop yelling and go file a bug at https://bugzilla.mindrot.org/ As I mentioned previously, your suggested change is wrong and we'd (at least) need to replace fd 1 with /dev/null prior to assigning it to the channel. -d
David Newall wrote:> Ssh does not, of itself, use stdout; it has no reason to keep stdout open.Does escape processing only ever use stderr? Type ENTER ~ ? in an open ssh session. (three characters, no spaces) And are sessions with channel muxing a concern? David Newall wrote:> I don't think you are trying to help.David, your communication style is horrible. It makes you look really bad and it significantly decreases the chances of you and your concern being taken seriously. I believe that you want to make a constructive contribution, but statements such as the above have the complete opposite effect! //Peter