Dear OpenSSH developers, OpenSSH setting non-blocking mode on its standard files creates serious problems. Setting non-blocking mode violates many of the semantics of how files are supposed to behave and most programs (and most, if not all, stdio libraries) are not prepared to deal with it. That wouldn't be a problem except that non-blocking mode is not a property of the file descriptor but a property of the underlying file table entry and thus affects *all* file descriptors that are bound to that file table entry, not just the one used to set non-blocking mode. Thus, you really shouldn't use non-blocking mode unless you're in complete control of the underlying file. Since the standard files (stdin, stdout, and stderr) are inherited from the parent process, that's never the case. Consider: $ cat bigfile | wc -c 10858893 $ (ssh localhost sleep 120& sleep 3; cat bigfile) | wc -c cat: stdout: Resource temporarily unavailable 270336 When ssh puts its stdout into non-blocking mode, it also puts cat's stdout into non-blocking mode. cat notices the problem, but doesn't actually handle it correctly (most likely because it's using stdio and thus *can't* handle it correctly), so the vast majority of the data just disappears into the bit bucket. I understand the necessity to keep ssh from blocking in order to keep port-forwarding working, but wouldn't it be possible to do that by just selecting for write before trying to write to stdout or stderr rather than setting non-blocking mode? -Larry Jones My brain is trying to kill me. -- Calvin
Larry Jones wrote:> Dear OpenSSH developers, > > OpenSSH setting non-blocking mode on its standard files creates serious > problems.I don't think your analysis is correct: setting nonblock on one side of a stdio connection shouldn't affect the other side (see the attached test program).> $ cat bigfile | wc -c > 10858893 > $ (ssh localhost sleep 120& sleep 3; cat bigfile) | wc -c > cat: stdout: Resource temporarily unavailable > 270336What platform are you using? This works fine on OpenBSD and Solaris. You could be running into a kernel bug.> I understand the necessity to keep ssh from blocking in order to keep > port-forwarding working, but wouldn't it be possible to do that by just > selecting for write before trying to write to stdout or stderr rather > than setting non-blocking mode?No - we cannot turn of non-blocking stdio in OpenSSH. select() will tell you that a fd is ready for writing, but not how much data you can write. So unless you are willing to do your IO one byte at a time, select()ing for each byte, you can still block. -d -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: testnonblock.c Url: http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20050707/97f35718/attachment.c
Larry> $ cat bigfile | wc -c Larry> 10858893 Larry> $ (ssh localhost sleep 120& sleep 3; cat bigfile) | wc -c Larry> cat: stdout: Resource temporarily unavailable Larry> 270336 Damien> What platform are you using? This works fine on OpenBSD and Solaris. Damien> You could be running into a kernel bug. For the record, I can reproduce this problem intermittently on OpenBSD: fire $ uname -a OpenBSD fire.0--0.org 3.6 GENERIC#304 sparc64 fire $ cat INBOX | wc -c 4106962 fire $ (ssh localhost sleep 120& sleep 3; cat INBOX) | wc -c 4106962 fire $ (ssh localhost sleep 120& sleep 3; cat INBOX) | wc -c cat: stdout: Resource temporarily unavailable 655360 Alex -- https://savannah.gnu.org/projects/libcvs-spec Access CVS through a library. PGP: ID: 0x23DC453B FPR: 42D0 66C2 9FF8 553A 373A B819 4C34 93BA 23DC 453B The pimp's trade must be carried out by intelligent people, is essential to any well-ordered society, and should have an official inspector. -- Don Quixote