logo       

System.Cmd.system/rawSystem set stdin/stdout to non-blocking mode: msg#00047

lang.haskell.glasgow.bugs

Subject: System.Cmd.system/rawSystem set stdin/stdout to non-blocking mode

Hi,

While tracking down a bug in Ginsu earlier, I found that the cause is an
unexpected side-effect of the System.Cmd functions: they set FD 0 (and
consequently anything that it's been dupped to, so probably FD 1 and FD
2 as well) to non-blocking mode. This will break any future usage of
stdin/stdout that doesn't expect to get an EAGAIN error -- for example,
Ginsu uses the curses library which won't update the screen correctly if
FD 1 is non-blocking. Worse, this is done before the fork(), so the
program that's run is also given its FDs in non-blocking mode, and will
thus suffer the same problems.

It appears that this is a consequence of
System.Process.Internals.runProcessPosix using "stdin", which sets FD 0
to be non-blocking.

Here's how to reproduce the problem on my system -- owing to the other
problem I've just reported (that queryFdOption doesn't work correctly),
you need to look at the strace output to see the state that the FD's
left in.

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 6.4
$ uname -a
Linux cartman.at.fivegeeks.net 2.6.12.2 #1 Thu Jul 14 15:28:07 BST 2005
i686 unknown unknown GNU/Linux
$ gcc -v
Reading specs from
/opt/packages/gcc-3.4.4/bin/../lib/gcc/i686-pc-linux-gnu/3.4.4/specs
Configured with: ./configure --prefix=/opt --sysconfdir=/etc
--localstatedir=/var --sharedstatedir=/var/com --enable-__cxa_atexit
--enable-threads=posix --enable-shared
--enable-languages=c,c++,java,f77,objc
Thread model: posix
gcc version 3.4.4
$ cat NonBlocking.hs
import System.Cmd
import System.Posix.IO

showNBR = do
v <- System.Posix.IO.queryFdOption 0 System.Posix.IO.NonBlockingRead
putStr $ "NonBlockingRead may or may not be " ++ (show v) ++ "\n"

main = do
showNBR
System.Cmd.rawSystem "echo" ["hello, world!"]
showNBR
$ ghc -o nonblocking -package unix NonBlocking.hs
$ ./nonblocking
NonBlockingRead may or may not be False
hello, world!
NonBlockingRead may or may not be False
[note that last result is wrong, but we can see what it should be:]
$ strace ./nonblocking 2>&1 | egrep '(ETFL|fork)'
fcntl64(0, F_GETFL) = 0x2 (flags O_RDWR)
fcntl64(0, F_GETFL) = 0x2 (flags O_RDWR)
fcntl64(0, F_SETFL, O_RDWR|O_NONBLOCK) = 0
vfork() = 5706
fcntl64(0, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK)
[i.e. FD 0's now got O_NONBLOCK -- and it did inside the echo too...]

I get the same result with Debian's GHC 6.4 packages. If you need any
more information, please let me know.

Thanks,

--
Adam Sampson <ats@xxxxxxxxx> <http://offog.org/>


<Prev in Thread] Current Thread [Next in Thread>
Google Custom Search

News | FAQ | advertise