X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=System%2FProcess.hs;h=f2e937eec455d0777478abf1ce8aafc463b24aa7;hb=6b1a36a595eddf1e124529646afdb75c76a9966d;hp=d4bc43f7717fb9572d6491902e690bd173577b31;hpb=d50c1eee6e446d385357f4d7079d700ed3275d74;p=haskell-directory.git diff --git a/System/Process.hs b/System/Process.hs index d4bc43f..f2e937e 100644 --- a/System/Process.hs +++ b/System/Process.hs @@ -81,7 +81,8 @@ runCommand string = do {- | Runs a raw command, optionally specifying 'Handle's from which to take the @stdin@, @stdout@ and @stderr@ channels for the new - process. + process (otherwise these handles are inherited from the current + process). Any 'Handle's passed to 'runProcess' are placed immediately in the closed state. @@ -237,11 +238,23 @@ waitForProcess :: ProcessHandle -> IO ExitCode waitForProcess ph = do - handle <- getProcessHandle ph - code <- throwErrnoIfMinus1 "waitForProcess" (c_waitForProcess handle) - if (code == 0) - then return ExitSuccess - else return (ExitFailure (fromIntegral code)) + p_ <- withProcessHandle ph $ \p_ -> return (p_,p_) + case p_ of + ClosedHandle e -> return e + OpenHandle h -> do + -- don't hold the MVar while we call c_waitForProcess... + -- (XXX but there's a small race window here during which another + -- thread could close the handle or call waitForProcess) + code <- throwErrnoIfMinus1 "waitForProcess" (c_waitForProcess h) + withProcessHandle ph $ \p_ -> + case p_ of + ClosedHandle e -> return (p_,e) + OpenHandle ph -> do + closePHANDLE ph + let e = if (code == 0) + then ExitSuccess + else (ExitFailure (fromIntegral code)) + return (ClosedHandle e, e) -- ---------------------------------------------------------------------------- -- terminateProcess @@ -256,8 +269,14 @@ waitForProcess ph = do -- an exit code of 1. terminateProcess :: ProcessHandle -> IO () terminateProcess ph = do - pid <- getProcessHandle ph - throwErrnoIfMinus1_ "terminateProcess" (c_terminateProcess pid) + withProcessHandle_ ph $ \p_ -> + case p_ of + ClosedHandle _ -> return p_ + OpenHandle h -> do + throwErrnoIfMinus1_ "terminateProcess" $ c_terminateProcess h + return p_ + -- does not close the handle, we might want to try terminating it + -- again, or get its exit code. -- ---------------------------------------------------------------------------- -- getProcessExitCode @@ -271,15 +290,21 @@ Subsequent calls to @getProcessExitStatus@ always return @'Just' -} getProcessExitCode :: ProcessHandle -> IO (Maybe ExitCode) getProcessExitCode ph = do - handle <- getProcessHandle ph - alloca $ \pExitCode -> do - res <- throwErrnoIfMinus1 "getProcessExitCode" (c_getProcessExitCode handle pExitCode) - code <- peek pExitCode - if res == 0 - then return Nothing - else if code == 0 - then return (Just ExitSuccess) - else return (Just (ExitFailure (fromIntegral code))) + withProcessHandle ph $ \p_ -> + case p_ of + ClosedHandle e -> return (p_, Just e) + OpenHandle h -> + alloca $ \pExitCode -> do + res <- throwErrnoIfMinus1 "getProcessExitCode" $ + c_getProcessExitCode h pExitCode + code <- peek pExitCode + if res == 0 + then return (p_, Nothing) + else do + closePHANDLE h + let e | code == 0 = ExitSuccess + | otherwise = ExitFailure (fromIntegral code) + return (ClosedHandle e, Just e) -- ---------------------------------------------------------------------------- -- Interface to C bits