Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
ede73d3
Bump directory upper bound to < 1.4
bgamari Dec 6, 2016
41cc846
Merge pull request #78 from haskell/bgamari-patch-1
snoyberg Dec 6, 2016
28946c6
Version bump for release #79
snoyberg Dec 9, 2016
dc4849d
runProcess.c: Clean up whitespace
bgamari Dec 12, 2016
9d68cb1
runProcess.c: Don't close already closed pipes
bgamari Dec 12, 2016
a71d831
Merge pull request #81 from bgamari/master
snoyberg Dec 13, 2016
85cc1d1
Update changelog for #81
snoyberg Dec 13, 2016
2307944
Relax version bounds.
Mistuke Jan 20, 2017
6d75056
Merge pull request #85 from Mistuke/bump-win32
snoyberg Jan 22, 2017
77df92f
#82, remove the incorrect notes that Handle's are in binary mode.
ndmitchell Jan 22, 2017
f044a18
#82, note that all created handles are in text mode.
ndmitchell Jan 22, 2017
0524859
Merge pull request #86 from ndmitchell/master
snoyberg Jan 22, 2017
684ce18
GH77: Add scaffolding.
Mistuke Dec 3, 2016
8080309
GH77: Fixed compilation
Mistuke Dec 4, 2016
d71248a
GH77: Add terminate job
Mistuke Dec 4, 2016
57e0c7f
GH77: Update readme and export list.
Mistuke Dec 4, 2016
f6de652
GH77: Replaced system and rawSystem
Mistuke Dec 4, 2016
3f440e2
GH77: Updated readme
Mistuke Dec 4, 2016
86b273c
GH77: Fix tests
Mistuke Dec 4, 2016
e7827bb
GH77: Add failing test for Windows.
Mistuke Dec 4, 2016
3bf217f
GH77: Working
Mistuke Dec 10, 2016
282aa2e
GH77: Finish implementation.
Mistuke Dec 10, 2016
e89d6e1
GH77: Update testsuite.
Mistuke Dec 10, 2016
2e3542d
GH77: update tests.
Mistuke Dec 11, 2016
eb85aac
GH77: fix tests
Mistuke Dec 11, 2016
605ce3e
GH77: Accept output.
Mistuke Dec 11, 2016
3a5935c
GH77: rewrote implementation.
Mistuke Jan 2, 2017
ae57e8c
GH77: fix compile errors.
Mistuke Jan 2, 2017
7ef688e
GH77: Update readme.
Mistuke Jan 5, 2017
c3c067b
GH77: restored compatibility.
Mistuke Jan 7, 2017
5a12fa4
GH77: rebased.
Mistuke Jan 7, 2017
e41616e
GH77: fix Posix.
Mistuke Jan 8, 2017
5a0d7bc
GH77: remove typo.
Mistuke Jan 8, 2017
ad967f8
GH77: fix pattern matching posix.
Mistuke Jan 8, 2017
2d6933b
GH77: replace <$> with fmap
Mistuke Jan 8, 2017
4a423ad
GH77: Add appropriate ifdefs.
Mistuke Jan 8, 2017
94a2140
GH77: fixed bug.
Mistuke Jan 16, 2017
523b3dd
GH77: Added note.'
Mistuke Jan 17, 2017
0f7b948
Updated based on review
Mistuke Jan 29, 2017
f8b53d8
rebased and set back WINDOWS_CCONV
Mistuke Jan 29, 2017
9bcbaeb
fix build.
Mistuke Jan 29, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 44 additions & 24 deletions System/Process.hs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ proc cmd args = CreateProcess { cmdspec = RawCommand cmd args,
create_new_console = False,
new_session = False,
child_group = Nothing,
child_user = Nothing }
child_user = Nothing,
use_process_jobs = False }

-- | Construct a 'CreateProcess' record for passing to 'createProcess',
-- representing a command to be passed to the shell.
Expand All @@ -133,7 +134,8 @@ shell str = CreateProcess { cmdspec = ShellCommand str,
create_new_console = False,
new_session = False,
child_group = Nothing,
child_user = Nothing }
child_user = Nothing,
use_process_jobs = False }

{- |
This is the most general way to spawn an external process. The
Expand Down Expand Up @@ -178,7 +180,8 @@ Note that @Handle@s provided for @std_in@, @std_out@, or @std_err@ via the
@UseHandle@ constructor will be closed by calling this function. This is not
always the desired behavior. In cases where you would like to leave the
@Handle@ open after spawning the child process, please use 'createProcess_'
instead.
instead. All created @Handle@s are initially in text mode; if you need them
to be in binary mode then use 'hSetBinaryMode'.

-}
createProcess
Expand Down Expand Up @@ -210,6 +213,7 @@ createProcess cp = do
-- > withCreateProcess (proc cmd args) { ... } $ \_ _ _ ph -> do
-- > ...
--
-- @since 1.4.3.0
-}
withCreateProcess
:: CreateProcess
Expand Down Expand Up @@ -592,8 +596,9 @@ waitForProcess ph@(ProcessHandle _ delegating_ctlc) = do
throwErrnoIfMinus1Retry_ "waitForProcess" (c_waitForProcess h pret)
modifyProcessHandle ph $ \p_' ->
case p_' of
ClosedHandle e -> return (p_',e)
OpenHandle ph' -> do
ClosedHandle e -> return (p_', e)
OpenExtHandle{} -> return (p_', ExitFailure (-1))
OpenHandle ph' -> do
closePHANDLE ph'
code <- peek pret
let e = if (code == 0)
Expand All @@ -603,7 +608,14 @@ waitForProcess ph@(ProcessHandle _ delegating_ctlc) = do
when delegating_ctlc $
endDelegateControlC e
return e

OpenExtHandle _ job iocp ->
#if defined(WINDOWS)
maybe (ExitFailure (-1)) mkExitCode `fmap` waitForJobCompletion job iocp timeout_Infinite
where mkExitCode code | code == 0 = ExitSuccess
| otherwise = ExitFailure $ fromIntegral code
#else
return $ ExitFailure (-1)
#endif

-- ----------------------------------------------------------------------------
-- getProcessExitCode
Expand All @@ -622,22 +634,29 @@ getProcessExitCode ph@(ProcessHandle _ delegating_ctlc) = do
(m_e, was_open) <- modifyProcessHandle ph $ \p_ ->
case p_ of
ClosedHandle e -> return (p_, (Just e, False))
OpenHandle h ->
open -> do
alloca $ \pExitCode -> do
res <- throwErrnoIfMinus1Retry "getProcessExitCode" $
c_getProcessExitCode h pExitCode
code <- peek pExitCode
if res == 0
then return (p_, (Nothing, False))
else do
closePHANDLE h
let e | code == 0 = ExitSuccess
| otherwise = ExitFailure (fromIntegral code)
return (ClosedHandle e, (Just e, True))
case getHandle open of
Nothing -> return (p_, (Nothing, False))
Just h -> do
res <- throwErrnoIfMinus1Retry "getProcessExitCode" $
c_getProcessExitCode h pExitCode
code <- peek pExitCode
if res == 0
then return (p_, (Nothing, False))
else do
closePHANDLE h
let e | code == 0 = ExitSuccess
| otherwise = ExitFailure (fromIntegral code)
return (ClosedHandle e, (Just e, True))
case m_e of
Just e | was_open && delegating_ctlc -> endDelegateControlC e
_ -> return ()
return m_e
where getHandle :: ProcessHandle__ -> Maybe PHANDLE
getHandle (OpenHandle h) = Just h
getHandle (ClosedHandle _) = Nothing
getHandle (OpenExtHandle h _ _) = Just h


-- ----------------------------------------------------------------------------
Expand All @@ -662,8 +681,13 @@ terminateProcess :: ProcessHandle -> IO ()
terminateProcess ph = do
withProcessHandle ph $ \p_ ->
case p_ of
ClosedHandle _ -> return ()
OpenHandle h -> do
ClosedHandle _ -> return ()
#if defined(WINDOWS)
OpenExtHandle{} -> terminateJob ph 1 >> return ()
#else
OpenExtHandle{} -> error "terminateProcess with OpenExtHandle should not happen on POSIX."
#endif
OpenHandle h -> do
throwErrnoIfMinus1Retry_ "terminateProcess" $ c_terminateProcess h
return ()
-- does not close the handle, we might want to try terminating it
Expand Down Expand Up @@ -773,8 +797,7 @@ runProcess cmd args mb_cwd mb_env mb_stdin mb_stdout mb_stderr = do

{- | Runs a command using the shell, and returns 'Handle's that may
be used to communicate with the process via its @stdin@, @stdout@,
and @stderr@ respectively. The 'Handle's are initially in binary
mode; if you need them to be in text mode then use 'hSetBinaryMode'.
and @stderr@ respectively.
-}
runInteractiveCommand
:: String
Expand All @@ -796,9 +819,6 @@ runInteractiveCommand string =

> (inp,out,err,pid) <- runInteractiveProcess "..."
> forkIO (hPutStr inp str)

The 'Handle's are initially in binary mode; if you need them to be
in text mode then use 'hSetBinaryMode'.
-}
runInteractiveProcess
:: FilePath -- ^ Filename of the executable (see 'RawCommand' for details)
Expand Down
25 changes: 23 additions & 2 deletions System/Process/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module System.Process.Common
, StdStream (..)
, ProcessHandle(..)
, ProcessHandle__(..)
, ProcRetHandles (..)
, withFilePathException
, PHANDLE
, modifyProcessHandle
Expand Down Expand Up @@ -94,13 +95,27 @@ data CreateProcess = CreateProcess{
-- Default: @Nothing@
--
-- @since 1.4.0.0
child_user :: Maybe UserID -- ^ Use posix setuid to set child process's user id; does nothing on other platforms.
child_user :: Maybe UserID, -- ^ Use posix setuid to set child process's user id; does nothing on other platforms.
--
-- Default: @Nothing@
--
-- @since 1.4.0.0
use_process_jobs :: Bool -- ^ On Windows systems this flag indicates that we should wait for the entire process tree
-- to finish before unblocking. On POSIX systems this flag is ignored.
--
-- Default: @False@
--
-- @since 1.5.0.0
} deriving (Show, Eq)

-- | contains the handles returned by a call to createProcess_Internal
data ProcRetHandles
= ProcRetHandles { hStdInput :: Maybe Handle
, hStdOutput :: Maybe Handle
, hStdError :: Maybe Handle
, procHandle :: ProcessHandle
}

data CmdSpec
= ShellCommand String
-- ^ A command line to execute using the shell
Expand Down Expand Up @@ -154,8 +169,14 @@ data StdStream
None of the process-creation functions in this library wait for
termination: they all return a 'ProcessHandle' which may be used
to wait for the process later.

On Windows a second wait method can be used to block for event
completion. This requires two handles. A process job handle and
a events handle to monitor.
-}
data ProcessHandle__ = OpenHandle PHANDLE | ClosedHandle ExitCode
data ProcessHandle__ = OpenHandle PHANDLE
| OpenExtHandle PHANDLE PHANDLE PHANDLE
| ClosedHandle ExitCode
data ProcessHandle = ProcessHandle !(MVar ProcessHandle__) !Bool

withFilePathException :: FilePath -> IO a -> IO a
Expand Down
28 changes: 24 additions & 4 deletions System/Process/Internals.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,19 @@ module System.Process.Internals (
PHANDLE, closePHANDLE, mkProcessHandle,
modifyProcessHandle, withProcessHandle,
CreateProcess(..),
CmdSpec(..), StdStream(..),
CmdSpec(..), StdStream(..), ProcRetHandles (..),
createProcess_,
runGenProcess_, --deprecated
fdToHandle,
startDelegateControlC,
endDelegateControlC,
stopDelegateControlC,
#ifndef WINDOWS
unwrapHandles,
#ifdef WINDOWS
terminateJob,
waitForJobCompletion,
timeout_Infinite,
#else
pPrPr_disableITimers, c_execvpe,
ignoreSignal, defaultSignal,
#endif
Expand All @@ -57,7 +62,6 @@ import System.Process.Posix
#endif

-- ----------------------------------------------------------------------------

-- | This function is almost identical to
-- 'System.Process.createProcess'. The only differences are:
--
Expand All @@ -66,6 +70,18 @@ import System.Process.Posix
-- * This function takes an extra @String@ argument to be used in creating
-- error messages.
--
-- * 'use_process_jobs' can be set in CreateProcess since 1.5.0.0 in order to create
-- an I/O completion port to monitor a process tree's progress on Windows.
--
-- The function also returns two new handles:
-- * an I/O Completion Port handle on which events
-- will be signaled.
-- * a Job handle which can be used to kill all running
-- processes.
--
-- On POSIX platforms these two new handles will always be Nothing
--
--
-- This function has been available from the "System.Process.Internals" module
-- for some time, and is part of the "System.Process" module since version
-- 1.2.1.0.
Expand All @@ -75,7 +91,7 @@ createProcess_
:: String -- ^ function name (for error messages)
-> CreateProcess
-> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
createProcess_ = createProcess_Internal
createProcess_ msg proc_ = unwrapHandles `fmap` createProcess_Internal msg proc_
{-# INLINE createProcess_ #-}

-- ------------------------------------------------------------------------
Expand Down Expand Up @@ -137,6 +153,10 @@ translate :: String -> String
translate = translateInternal
{-# INLINE translate #-}

-- ---------------------------------------------------------------------------
-- unwrapHandles
unwrapHandles :: ProcRetHandles -> (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
unwrapHandles r = (hStdInput r, hStdOutput r, hStdError r, procHandle r)

-- ----------------------------------------------------------------------------
-- Deprecated / compat
Expand Down
13 changes: 9 additions & 4 deletions System/Process/Posix.hs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ withCEnvironment envir act =
createProcess_Internal
:: String
-> CreateProcess
-> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
-> IO ProcRetHandles
createProcess_Internal fun
CreateProcess{ cmdspec = cmdsp,
cwd = mb_cwd,
Expand Down Expand Up @@ -166,7 +166,11 @@ createProcess_Internal fun
hndStdError <- mbPipe mb_stderr pfdStdError ReadMode

ph <- mkProcessHandle proc_handle mb_delegate_ctlc
return (hndStdInput, hndStdOutput, hndStdError, ph)
return ProcRetHandles { hStdInput = hndStdInput
, hStdOutput = hndStdOutput
, hStdError = hndStdError
, procHandle = ph
}

{-# NOINLINE runInteractiveProcess_lock #-}
runInteractiveProcess_lock :: MVar ()
Expand Down Expand Up @@ -291,7 +295,8 @@ interruptProcessGroupOfInternal
interruptProcessGroupOfInternal ph = do
withProcessHandle ph $ \p_ -> do
case p_ of
ClosedHandle _ -> return ()
OpenHandle h -> do
OpenExtHandle{} -> return ()
ClosedHandle _ -> return ()
OpenHandle h -> do
pgid <- getProcessGroupIDOf h
signalProcessGroup sigINT pgid
Loading