[commit: packages/process] master: Check if waitpidLock is held in getProcessExitCode (c722d8b)
git at git.haskell.org
git at git.haskell.org
Wed Jul 19 21:19:25 UTC 2017
Repository : ssh://git@git.haskell.org/process
On branch : master
Link : http://ghc.haskell.org/trac/ghc/changeset/c722d8b85568d2185dbe716a9988697eccb27e56/process
>---------------------------------------------------------------
commit c722d8b85568d2185dbe716a9988697eccb27e56
Author: Charles Cooper <cooper.charles.m at gmail.com>
Date: Fri Feb 17 12:03:01 2017 -0800
Check if waitpidLock is held in getProcessExitCode
>---------------------------------------------------------------
c722d8b85568d2185dbe716a9988697eccb27e56
System/Process.hs | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/System/Process.hs b/System/Process.hs
index 50c787e..0a5e93e 100644
--- a/System/Process.hs
+++ b/System/Process.hs
@@ -77,7 +77,7 @@ import System.Process.Internals
import Control.Concurrent
import Control.DeepSeq (rnf)
-import Control.Exception (SomeException, mask, try, throwIO)
+import Control.Exception (SomeException, mask, bracket, try, throwIO)
import qualified Control.Exception as C
import Control.Monad
import Data.Maybe
@@ -635,7 +635,7 @@ when the process died as the result of a signal.
-}
getProcessExitCode :: ProcessHandle -> IO (Maybe ExitCode)
-getProcessExitCode ph@(ProcessHandle _ delegating_ctlc _) = do
+getProcessExitCode ph@(ProcessHandle _ delegating_ctlc _) = tryLockWaitpid $ do
(m_e, was_open) <- modifyProcessHandle ph $ \p_ ->
case p_ of
ClosedHandle e -> return (p_, (Just e, False))
@@ -663,6 +663,23 @@ getProcessExitCode ph@(ProcessHandle _ delegating_ctlc _) = do
getHandle (ClosedHandle _) = Nothing
getHandle (OpenExtHandle h _ _) = Just h
+ -- If somebody is currently holding the waitpid lock, we don't want to
+ -- accidentally remove the pid from the process table.
+ -- Try acquiring the waitpid lock. If it is held, we are done
+ -- since that means the process is still running and we can return
+ -- `Nothing`. If it is not held, acquire it so we can run the
+ -- (non-blocking) call to `waitpid` without worrying about any
+ -- other threads calling it at the same time.
+ tryLockWaitpid :: IO (Maybe ExitCode) -> IO (Maybe ExitCode)
+ tryLockWaitpid action = bracket acquire release between
+ where
+ acquire = tryTakeMVar (waitpidLock ph)
+ release m = case m of
+ Nothing -> return ()
+ Just () -> putMVar (waitpidLock ph) ()
+ between m = case m of
+ Nothing -> return Nothing
+ Just () -> do action
-- ----------------------------------------------------------------------------
-- terminateProcess
More information about the ghc-commits
mailing list