{-# LANGUAGE CPP #-}
{-# OPTIONS_HADDOCK not-home #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE InterruptibleFFI #-}
module System.Process.Internals (
ProcessHandle(..), ProcessHandle__(..),
PHANDLE, closePHANDLE, mkProcessHandle,
#if defined(mingw32_HOST_OS)
CGid(..),
#else
CGid,
#endif
GroupID,
UserID,
modifyProcessHandle, withProcessHandle,
CreateProcess(..),
CmdSpec(..), StdStream(..), ProcRetHandles (..),
createProcess_,
runGenProcess_,
fdToHandle,
startDelegateControlC,
endDelegateControlC,
stopDelegateControlC,
unwrapHandles,
#if defined(mingw32_HOST_OS)
terminateJob,
terminateJobUnsafe,
waitForJobCompletion,
timeout_Infinite,
#else
#if !defined(javascript_HOST_ARCH)
pPrPr_disableITimers, c_execvpe,
runInteractiveProcess_lock,
#endif
ignoreSignal, defaultSignal,
#endif
withFilePathException, withCEnvironment,
translate,
createPipe,
createPipeFd,
interruptProcessGroupOf,
withForkWait,
ignoreSigPipe,
) where
import Control.Concurrent
import Control.Exception (SomeException, mask, try, throwIO)
import qualified Control.Exception as C
import Foreign.C
import System.IO
import GHC.IO.Exception ( IOErrorType(..), IOException(..) )
import GHC.IO.Handle.FD (fdToHandle)
import System.Posix.Internals (FD)
import System.Process.Common
#if defined(javascript_HOST_ARCH)
import System.Process.JavaScript
#elif defined(mingw32_HOST_OS)
import System.Process.Windows
#else
import System.Process.Posix
#endif
createProcess_
:: String
-> CreateProcess
-> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
createProcess_ :: String
-> CreateProcess
-> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
createProcess_ String
msg CreateProcess
proc_ = ProcRetHandles
-> (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
unwrapHandles (ProcRetHandles
-> (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle))
-> IO ProcRetHandles
-> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` String -> CreateProcess -> IO ProcRetHandles
createProcess_Internal String
msg CreateProcess
proc_
{-# INLINE createProcess_ #-}
translate :: String -> String
translate :: String -> String
translate = String -> String
translateInternal
{-# INLINE translate #-}
unwrapHandles :: ProcRetHandles -> (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
unwrapHandles :: ProcRetHandles
-> (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
unwrapHandles ProcRetHandles
r = (ProcRetHandles -> Maybe Handle
hStdInput ProcRetHandles
r, ProcRetHandles -> Maybe Handle
hStdOutput ProcRetHandles
r, ProcRetHandles -> Maybe Handle
hStdError ProcRetHandles
r, ProcRetHandles -> ProcessHandle
procHandle ProcRetHandles
r)
{-# DEPRECATED runGenProcess_
"Please do not use this anymore, use the ordinary 'System.Process.createProcess'. If you need the SIGINT handling, use delegate_ctlc = True (runGenProcess_ is now just an imperfectly emulated stub that probably duplicates or overrides your own signal handling)." #-}
runGenProcess_
:: String
-> CreateProcess
-> Maybe CLong
-> Maybe CLong
-> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
runGenProcess_ :: String
-> CreateProcess
-> Maybe CLong
-> Maybe CLong
-> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
runGenProcess_ String
fun CreateProcess
c (Just CLong
sig) (Just CLong
sig') | CLong -> Bool
isDefaultSignal CLong
sig Bool -> Bool -> Bool
&& CLong
sig CLong -> CLong -> Bool
forall a. Eq a => a -> a -> Bool
== CLong
sig'
= String
-> CreateProcess
-> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
createProcess_ String
fun CreateProcess
c { delegate_ctlc = True }
runGenProcess_ String
fun CreateProcess
c Maybe CLong
_ Maybe CLong
_ = String
-> CreateProcess
-> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
createProcess_ String
fun CreateProcess
c
createPipe :: IO (Handle, Handle)
createPipe :: IO (Handle, Handle)
createPipe = IO (Handle, Handle)
createPipeInternal
{-# INLINE createPipe #-}
createPipeFd :: IO (FD, FD)
createPipeFd :: IO (FD, FD)
createPipeFd = IO (FD, FD)
createPipeInternalFd
{-# INLINE createPipeFd #-}
interruptProcessGroupOf
:: ProcessHandle
-> IO ()
interruptProcessGroupOf :: ProcessHandle -> IO ()
interruptProcessGroupOf = ProcessHandle -> IO ()
interruptProcessGroupOfInternal
withForkWait :: IO () -> (IO () -> IO a) -> IO a
withForkWait :: forall a. IO () -> (IO () -> IO a) -> IO a
withForkWait IO ()
async IO () -> IO a
body = do
MVar (Either SomeException ())
waitVar <- IO (MVar (Either SomeException ()))
forall a. IO (MVar a)
newEmptyMVar :: IO (MVar (Either SomeException ()))
((forall a. IO a -> IO a) -> IO a) -> IO a
forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
mask (((forall a. IO a -> IO a) -> IO a) -> IO a)
-> ((forall a. IO a -> IO a) -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \forall a. IO a -> IO a
restore -> do
ThreadId
tid <- IO () -> IO ThreadId
forkIO (IO () -> IO ThreadId) -> IO () -> IO ThreadId
forall a b. (a -> b) -> a -> b
$ IO () -> IO (Either SomeException ())
forall e a. Exception e => IO a -> IO (Either e a)
try (IO () -> IO ()
forall a. IO a -> IO a
restore IO ()
async) IO (Either SomeException ())
-> (Either SomeException () -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= MVar (Either SomeException ()) -> Either SomeException () -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar (Either SomeException ())
waitVar
let wait :: IO ()
wait = MVar (Either SomeException ()) -> IO (Either SomeException ())
forall a. MVar a -> IO a
takeMVar MVar (Either SomeException ())
waitVar IO (Either SomeException ())
-> (Either SomeException () -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (SomeException -> IO ())
-> (() -> IO ()) -> Either SomeException () -> IO ()
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either SomeException -> IO ()
forall e a. Exception e => e -> IO a
throwIO () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return
IO a -> IO a
forall a. IO a -> IO a
restore (IO () -> IO a
body IO ()
wait) IO a -> IO () -> IO a
forall a b. IO a -> IO b -> IO a
`C.onException` ThreadId -> IO ()
killThread ThreadId
tid
ignoreSigPipe :: IO () -> IO ()
ignoreSigPipe :: IO () -> IO ()
ignoreSigPipe = (IOException -> IO ()) -> IO () -> IO ()
forall e a. Exception e => (e -> IO a) -> IO a -> IO a
C.handle ((IOException -> IO ()) -> IO () -> IO ())
-> (IOException -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ \IOException
e -> case IOException
e of
IOError { ioe_type :: IOException -> IOErrorType
ioe_type = IOErrorType
ResourceVanished
, ioe_errno :: IOException -> Maybe FD
ioe_errno = Just FD
ioe }
| FD -> Errno
Errno FD
ioe Errno -> Errno -> Bool
forall a. Eq a => a -> a -> Bool
== Errno
ePIPE -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
IOException
_ -> IOException -> IO ()
forall e a. Exception e => e -> IO a
throwIO IOException
e