diff --git a/ghc/lib/posix/Posix.lhs b/ghc/lib/posix/Posix.lhs index fa3c233592bd79be7eed64ef93731952456c6998..8eeb0f7b4856d34e7ddf2ac34001adcba3f5b1c2 100644 --- a/ghc/lib/posix/Posix.lhs +++ b/ghc/lib/posix/Posix.lhs @@ -14,6 +14,7 @@ module Posix ( module PosixTTY, runProcess, + exec, ByteCount, Fd, intToFd, @@ -48,6 +49,26 @@ import PosixUtil -- [OLD COMMENT:] -- runProcess is our candidate for the high-level OS-independent primitive -- If accepted, it will be moved out of Posix into LibSystem. +-- +-- ***NOTE***: make sure you completely force the evaluation of the path +-- and arguments to the child before calling runProcess. If you don't do +-- this *and* the arguments from runProcess are read in from a file lazily, +-- be prepared for some rather weird parent-child file I/O behaviour. +-- +-- [If you don't force the args, consider the case where the +-- arguments emanate from a file that is read lazily, using hGetContents +-- or some such. Since a child of a fork() inherits the opened files of +-- the parent, the child can force the evaluation of the arguments and +-- read them off the file without any problems. The problem is that +-- while the child share a file table with the parent, it has +-- separate buffers, so a child may fill up its (copy of) the buffer, but +-- only read it partially. When the *parent* tries to read from the shared file again, +-- the (shared) file offset will have been stepped on by whatever number of chars +-- that was copied into the file buffer of the child. i.e., the unused parts of the +-- buffer will *not* be seen, resulting in random/unpredicatable results. +-- +-- Based on a true (, debugged :-) story. +-- ] import Directory ( setCurrentDirectory ) @@ -60,19 +81,19 @@ runProcess :: FilePath -- Command -> Maybe Handle -- stdout -> Maybe Handle -- stderr -> IO () -runProcess path args env dir stdin stdout stderr = - forkProcess >>= \ pid -> +runProcess path args env dir stdin stdout stderr = do + pid <- forkProcess case pid of Nothing -> doTheBusiness Just x -> return () where doTheBusiness :: IO () - doTheBusiness = - maybeChangeWorkingDirectory >> - maybeDup2 0 stdin >> - maybeDup2 1 stdout >> - maybeDup2 2 stderr >> - executeFile path True args env >> + doTheBusiness = do + maybeChangeWorkingDirectory + maybeDup2 0 stdin + maybeDup2 1 stdout + maybeDup2 2 stderr + executeFile path True args env syserr "runProcess" maybeChangeWorkingDirectory :: IO () @@ -84,8 +105,9 @@ runProcess path args env dir stdin stdout stderr = maybeDup2 :: Int -> Maybe Handle -> IO () maybeDup2 dest h = case h of Nothing -> return () - Just x -> handleToFd x >>= \ src -> - dupTo src (intToFd dest) >> - return () + Just x -> do + src <- handleToFd x + dupTo src (intToFd dest) + return () \end{code}