
Bryan O'Sullivan wrote:
Simon Marlow wrote:
We can't just take a file descriptor out of non-blocking mode, because due to broken POSIX semantics that would screw up GHC's use of the file descriptor (there's no way to set non-blocking mode per-FD).
Are you sure? I'd expect fcntl will do the trick. And you don't have to set non-blocking mode until after the fork, in the child, so GHC shouldn't see any consequences at all.
I'm sure, yes. The non-blocking flag is part of the "open file description" (see [1], [2]), not the file descriptor. This is why you use F_SETFL rather than F_SETFD to set it with fcntl(). When you dup() a file descriptor, the two FDs share a non-blocking flag, just as they share a file pointer. A TTY also has a single non-blocking flag, which all FDs (read & write) share. So when GHC sets its stdin to non-blocking mode, and stdin is the current TTY, anyone else writing to the TTY also gets non-blocking mode, hence the tee bug. Just to make sure I wasn't deluded, I just managed to demonstrate this with a couple of small test programs, which I'll attach - you need to compile them both, then run "./nonblock1 | ./nonblock2", and hit enter. Notice that the C program is seeing O_NONBLOCK set on its stdout/stderr descriptors, despite not having set it. Fortunately each end of a pipe has a separate non-blocking flag, which is why runInteractiveProcess doesn't get into difficulties, although runProcess does (see John's original message). [1] http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_0... [2] http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_0...
I've just milestoned this bug for 6.6.2, so I promise to at least try to fix it before then...
I've got a patch partially written, which shouldn't take more than an hour to finish off and test. So don't worry about this just yet.
neat - is it based on the patch attached to the bug, or did you do something
different?
Cheers,
Simon
import System.IO
main = do getLine; putStr "Hello World!\n"; hFlush stdout; getLine
#include