On Windows, attach a finalizer to the ProcessHandle so that we can
call CloseHandle() when the handle is no longer in use. Previously we
were calling CloseHandle() in waitForProcess and terminateProcess,
which prevented making multiple calls to these functions on the same
handle.
hndStdInput <- fdToHandle pfdStdInput WriteMode
hndStdOutput <- fdToHandle pfdStdOutput ReadMode
hndStdError <- fdToHandle pfdStdError ReadMode
hndStdInput <- fdToHandle pfdStdInput WriteMode
hndStdOutput <- fdToHandle pfdStdOutput ReadMode
hndStdError <- fdToHandle pfdStdError ReadMode
- return (hndStdInput, hndStdOutput, hndStdError, ProcessHandle proc_handle)
+ ph <- mkProcessHandle proc_handle
+ return (hndStdInput, hndStdOutput, hndStdError, ph)
foreign import ccall unsafe "runInteractiveProcess"
c_runInteractiveProcess
foreign import ccall unsafe "runInteractiveProcess"
c_runInteractiveProcess
hndStdInput <- fdToHandle pfdStdInput WriteMode
hndStdOutput <- fdToHandle pfdStdOutput ReadMode
hndStdError <- fdToHandle pfdStdError ReadMode
hndStdInput <- fdToHandle pfdStdInput WriteMode
hndStdOutput <- fdToHandle pfdStdOutput ReadMode
hndStdError <- fdToHandle pfdStdError ReadMode
- return (hndStdInput, hndStdOutput, hndStdError,
- ProcessHandle proc_handle)
+ ph <- mkProcessHandle proc_handle
+ return (hndStdInput, hndStdOutput, hndStdError, ph)
foreign import ccall unsafe "runInteractiveProcess"
c_runInteractiveProcess
foreign import ccall unsafe "runInteractiveProcess"
c_runInteractiveProcess
waitForProcess
:: ProcessHandle
-> IO ExitCode
waitForProcess
:: ProcessHandle
-> IO ExitCode
-waitForProcess (ProcessHandle handle) = do
+waitForProcess ph = do
+ handle <- getProcessHandle ph
code <- throwErrnoIfMinus1 "waitForProcess" (c_waitForProcess handle)
if (code == 0)
then return ExitSuccess
code <- throwErrnoIfMinus1 "waitForProcess" (c_waitForProcess handle)
if (code == 0)
then return ExitSuccess
-- On Windows systems, the Win32 @TerminateProcess@ function is called, passing
-- an exit code of 1.
terminateProcess :: ProcessHandle -> IO ()
-- On Windows systems, the Win32 @TerminateProcess@ function is called, passing
-- an exit code of 1.
terminateProcess :: ProcessHandle -> IO ()
-terminateProcess (ProcessHandle pid) =
+terminateProcess ph = do
+ pid <- getProcessHandle ph
throwErrnoIfMinus1_ "terminateProcess" (c_terminateProcess pid)
-- ----------------------------------------------------------------------------
throwErrnoIfMinus1_ "terminateProcess" (c_terminateProcess pid)
-- ----------------------------------------------------------------------------
'ExitSuccess'@, regardless of what the original exit code was.
-}
getProcessExitCode :: ProcessHandle -> IO (Maybe ExitCode)
'ExitSuccess'@, regardless of what the original exit code was.
-}
getProcessExitCode :: ProcessHandle -> IO (Maybe ExitCode)
-getProcessExitCode (ProcessHandle handle) =
+getProcessExitCode ph = do
+ handle <- getProcessHandle ph
alloca $ \pExitCode -> do
res <- throwErrnoIfMinus1 "getProcessExitCode" (c_getProcessExitCode handle pExitCode)
code <- peek pExitCode
alloca $ \pExitCode -> do
res <- throwErrnoIfMinus1 "getProcessExitCode" (c_getProcessExitCode handle pExitCode)
code <- peek pExitCode
-- #hide
module System.Process.Internals (
-- #hide
module System.Process.Internals (
- ProcessHandle(..), PHANDLE,
+ ProcessHandle(..), PHANDLE, getProcessHandle, mkProcessHandle,
#if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)
pPrPr_disableITimers, c_execvpe,
# ifdef __GLASGOW_HASKELL__
#if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)
pPrPr_disableITimers, c_execvpe,
# ifdef __GLASGOW_HASKELL__
import System.IO ( Handle )
#else
import Data.Word ( Word32 )
import System.IO ( Handle )
#else
import Data.Word ( Word32 )
#endif
import Data.Maybe ( fromMaybe )
#endif
import Data.Maybe ( fromMaybe )
to wait for the process later.
-}
#if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)
to wait for the process later.
-}
#if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)
+newtype ProcessHandle = ProcessHandle PHANDLE
+
+getProcessHandle :: ProcessHandle -> IO PHANDLE
+getProcessHandle (ProcessHandle p) = return p
+
+mkProcessHandle :: PHANDLE -> IO ProcessHandle
+mkProcessHandle p = return (ProcessHandle p)
+
+newtype ProcessHandle = ProcessHandle (IORef PHANDLE)
+
+getProcessHandle :: ProcessHandle -> IO PHANDLE
+getProcessHandle (ProcessHandle ior) = readIORef ior
+
+-- On Windows, we have to close this HANDLE when it is no longer required,
+-- hence we add a finalizer to it, using an IORef as the box on which to
+-- attach the finalizer.
+mkProcessHandle :: PHANDLE -> IO ProcessHandle
+mkProcessHandle h = do
+ ioref <- newIORef h
+ mkWeakIORef ioref (c_CloseHandle h)
+ return (ProcessHandle ioref)
+
+foreign import stdcall unsafe "CloseHandle"
+ c_CloseHandle
+ :: PHANDLE
+ -> IO ()
-newtype ProcessHandle = ProcessHandle PHANDLE
-
-- ----------------------------------------------------------------------------
#if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)
-- ----------------------------------------------------------------------------
#if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)
c_runProcess pargs pWorkDir pEnv
fd_stdin fd_stdout fd_stderr
set_int inthand set_quit quithand
c_runProcess pargs pWorkDir pEnv
fd_stdin fd_stdout fd_stderr
set_int inthand set_quit quithand
- return (ProcessHandle ph)
foreign import ccall unsafe "runProcess"
c_runProcess
foreign import ccall unsafe "runProcess"
c_runProcess
proc_handle <- throwErrnoIfMinus1 fun
(c_runProcess pcmdline pWorkDir pEnv
fd_stdin fd_stdout fd_stderr)
proc_handle <- throwErrnoIfMinus1 fun
(c_runProcess pcmdline pWorkDir pEnv
fd_stdin fd_stdout fd_stderr)
- return (ProcessHandle proc_handle)
+ mkProcessHandle proc_handle
foreign import ccall unsafe "runProcess"
c_runProcess
foreign import ccall unsafe "runProcess"
c_runProcess
-
- CloseHandle((HANDLE) handle);
-
- CloseHandle((HANDLE) handle);
-
- CloseHandle((HANDLE) handle);