On 14/10/17 07:44, Damien Miller wrote:> On Fri, 13 Oct 2017, David Newall wrote: >> On 13/10/17 16:22, Damien Miller wrote: >> > At a minimum, I think we'd have to dup2 a fd to /dev/null to >> > STDOUT_FILENO so writes to stdout (e.g. from ill-behaved >> > libraries) have somewhere to go. >> >> Would that really be useful?? Output from Ill-behaved libraries, >> written fd 1, already go to the same place.? Don't forget, dup does >> not create a new file, it creates a duplicate handle to the same >> file.? I'm proposing getting rid of the duplicate. > Then what happens to stdout output between the time that the channel > holding fd 1 closes and the time ssh exits?The same thing that already happens: After the remote program closes stdout, any further attempt to write to that descriptor will fail; the program cannot continue to write to stdout after closing it; that is already the case.? The difference is that ssh will also close it's stdout; currently it keeps it open, which is an error.
> On Oct 13, 2017, at 22:37, David Newall <openssh at davidnewall.com> wrote: > >> On 14/10/17 07:44, Damien Miller wrote: >>> On Fri, 13 Oct 2017, David Newall wrote: >>> On 13/10/17 16:22, Damien Miller wrote: >>> > At a minimum, I think we'd have to dup2 a fd to /dev/null to >>> > STDOUT_FILENO so writes to stdout (e.g. from ill-behaved >>> > libraries) have somewhere to go. >>> >>> Would that really be useful? Output from Ill-behaved libraries, >>> written fd 1, already go to the same place. Don't forget, dup does >>> not create a new file, it creates a duplicate handle to the same >>> file. I'm proposing getting rid of the duplicate. >> Then what happens to stdout output between the time that the channel >> holding fd 1 closes and the time ssh exits? > > The same thing that already happens: After the remote program closes stdout, any further attempt to write to that descriptor will fail; the program cannot continue to write to stdout after closing it; that is already the case. The difference is that ssh will also close it's stdout; currently it keeps it open, which is an error.Why should ssh close its stdout because the remote program has redirected its stdout? If you want local stdout redirected, redirect it locally. What should happen in the following scenarios? (1) sh -c 'cat' >/dev/null | ( while read X; do echo $X; done; echo EOF ) (2) ssh remotehost 'cat' >/dev/null | ( while read X; do echo $X; done; echo EOF ) (3) sh -c 'cat >/dev/null; echo BLAH' | ( while read X; do echo $X; done; echo EOF ) (4) ssh remotehost 'cat >/dev/null; echo BLAH' | ( while read X; do echo $X; done; echo EOF ) (5) ( sh -c 'cat >/dev/null'; echo BLAH ) | ( while read X; do echo $X; done; echo EOF ) I don't think that just because a remote file descriptor has closed, the local one should be closed until the local process has finished with stdout. Only (1) and (2) above should produce 'EOF' immediately, which is exactly what happens for me (sh="GNU bash 3.2.57(1)", ssh="Apple OpenSSH_6.9p1" on OS X 10.11.6). In particular, 'sh -c "cat >/dev/null" | (while read X; do echo $X; done; echo EOF )' does not produce immediate 'EOF'. -- jim knoble | jmknoble at pobox.com
On Sun, Oct 15, 2017 at 1:36 AM, Jim Knoble <jmknoble at pobox.com> wrote:> > In particular, 'sh -c "cat >/dev/null" | (while read X; do echo $X; done; > echo EOF )' does not produce immediate 'EOF'. >The shell does not handle "cat > /dev/null" and "exec cat > /dev/null" in the same way. See the following strace output: $ strace sh -c "cat > /dev/null" [...] open("/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 fcntl(1, F_DUPFD, 10) = 10 close(1) = 0 fcntl(10, F_SETFD, FD_CLOEXEC) = 0 dup2(3, 1) = 1 close(3) = 0 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fd55c1dd9d0) = 27476 wait4(-1, $ strace sh -c "exec cat > /dev/null" [...] open("/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 fcntl(1, F_DUPFD, 10) = 10 close(1) = 0 fcntl(10, F_SETFD, FD_CLOEXEC) = 0 dup2(3, 1) = 1 close(3) = 0 execve("/bin/cat", ["cat"], [/* 32 vars */]) = 0 [...]