{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
#include <ghcplatform.h>
module System.Process.Posix
( mkProcessHandle
, translateInternal
, createProcess_Internal
, withCEnvironment
, closePHANDLE
, startDelegateControlC
, endDelegateControlC
, stopDelegateControlC
, isDefaultSignal
, ignoreSignal
, defaultSignal
, c_execvpe
, pPrPr_disableITimers
, createPipeInternal
, createPipeInternalFd
, interruptProcessGroupOfInternal
, runInteractiveProcess_lock
) where
import Control.Concurrent
import Control.Exception
import Data.Bits
import Foreign.C
import Foreign.Marshal
import Foreign.Ptr
import Foreign.Storable
import System.IO.Unsafe
import Control.Monad
import Data.Char
import System.IO
import System.Posix.Process.Internals ( pPrPr_disableITimers, c_execvpe )
import System.Posix.Types
import System.Posix.Internals
import GHC.IO.Exception
import System.Posix.Signals as Sig
import qualified System.Posix.IO as Posix
import System.Posix.Process (getProcessGroupIDOf)
import System.Process.Common hiding (mb_delegate_ctlc)
#if defined(wasm32_HOST_ARCH)
import System.IO.Error
#endif
#include "HsProcessConfig.h"
#include "processFlags.h"
mkProcessHandle :: PHANDLE -> Bool -> IO ProcessHandle
mkProcessHandle :: PHANDLE -> Bool -> IO ProcessHandle
mkProcessHandle PHANDLE
p Bool
mb_delegate_ctlc = do
m <- ProcessHandle__ -> IO (MVar ProcessHandle__)
forall a. a -> IO (MVar a)
newMVar (PHANDLE -> ProcessHandle__
OpenHandle PHANDLE
p)
l <- newMVar ()
return (ProcessHandle m mb_delegate_ctlc l)
closePHANDLE :: PHANDLE -> IO ()
closePHANDLE :: PHANDLE -> IO ()
closePHANDLE PHANDLE
_ = () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
commandToProcess :: CmdSpec -> (FilePath, [String])
commandToProcess :: CmdSpec -> (FilePath, [FilePath])
commandToProcess (ShellCommand FilePath
string) = (FilePath
"/bin/sh", [FilePath
"-c", FilePath
string])
commandToProcess (RawCommand FilePath
cmd [FilePath]
args) = (FilePath
cmd, [FilePath]
args)
translateInternal :: String -> String
translateInternal :: FilePath -> FilePath
translateInternal FilePath
"" = FilePath
"''"
translateInternal FilePath
str
| (Char -> Bool) -> FilePath -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
goodChar FilePath
str = FilePath
str
| Bool
otherwise = Char
'\'' Char -> FilePath -> FilePath
forall a. a -> [a] -> [a]
: (Char -> FilePath -> FilePath) -> FilePath -> FilePath -> FilePath
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Char -> FilePath -> FilePath
escape FilePath
"'" FilePath
str
where escape :: Char -> FilePath -> FilePath
escape Char
'\'' = FilePath -> FilePath -> FilePath
showString FilePath
"'\\''"
escape Char
c = Char -> FilePath -> FilePath
showChar Char
c
goodChar :: Char -> Bool
goodChar Char
c = Char -> Bool
isAlphaNum Char
c Bool -> Bool -> Bool
|| Char
c Char -> FilePath -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` FilePath
"-_.,/"
withCEnvironment :: [(String,String)] -> (Ptr CString -> IO a) -> IO a
withCEnvironment :: forall a. [(FilePath, FilePath)] -> (Ptr CString -> IO a) -> IO a
withCEnvironment [(FilePath, FilePath)]
envir Ptr CString -> IO a
act =
let env' :: [FilePath]
env' = ((FilePath, FilePath) -> FilePath)
-> [(FilePath, FilePath)] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (\(FilePath
name, FilePath
val) -> FilePath
name FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ (Char
'='Char -> FilePath -> FilePath
forall a. a -> [a] -> [a]
:FilePath
val)) [(FilePath, FilePath)]
envir
in (FilePath -> (CString -> IO a) -> IO a)
-> [FilePath] -> ([CString] -> IO a) -> IO a
forall a b res.
(a -> (b -> res) -> res) -> [a] -> ([b] -> res) -> res
withMany FilePath -> (CString -> IO a) -> IO a
forall a. FilePath -> (CString -> IO a) -> IO a
withFilePath [FilePath]
env' (\[CString]
pEnv -> CString -> [CString] -> (Ptr CString -> IO a) -> IO a
forall a b. Storable a => a -> [a] -> (Ptr a -> IO b) -> IO b
withArray0 CString
forall a. Ptr a
nullPtr [CString]
pEnv Ptr CString -> IO a
act)
createProcess_Internal
:: String
-> CreateProcess
-> IO ProcRetHandles
createProcess_Internal :: FilePath -> CreateProcess -> IO ProcRetHandles
createProcess_Internal FilePath
fun
CreateProcess{ cmdspec :: CreateProcess -> CmdSpec
cmdspec = CmdSpec
cmdsp,
cwd :: CreateProcess -> Maybe FilePath
cwd = Maybe FilePath
mb_cwd,
env :: CreateProcess -> Maybe [(FilePath, FilePath)]
env = Maybe [(FilePath, FilePath)]
mb_env,
std_in :: CreateProcess -> StdStream
std_in = StdStream
mb_stdin,
std_out :: CreateProcess -> StdStream
std_out = StdStream
mb_stdout,
std_err :: CreateProcess -> StdStream
std_err = StdStream
mb_stderr,
close_fds :: CreateProcess -> Bool
close_fds = Bool
mb_close_fds,
create_group :: CreateProcess -> Bool
create_group = Bool
mb_create_group,
delegate_ctlc :: CreateProcess -> Bool
delegate_ctlc = Bool
mb_delegate_ctlc,
detach_console :: CreateProcess -> Bool
detach_console = Bool
mb_detach_console,
create_new_console :: CreateProcess -> Bool
create_new_console = Bool
mb_create_new_console,
new_session :: CreateProcess -> Bool
new_session = Bool
mb_new_session,
child_group :: CreateProcess -> Maybe GroupID
child_group = Maybe GroupID
mb_child_group,
child_user :: CreateProcess -> Maybe UserID
child_user = Maybe UserID
mb_child_user }
= do
let (FilePath
cmd,[FilePath]
args) = CmdSpec -> (FilePath, [FilePath])
commandToProcess CmdSpec
cmdsp
FilePath -> IO ProcRetHandles -> IO ProcRetHandles
forall a. FilePath -> IO a -> IO a
withFilePathException FilePath
cmd (IO ProcRetHandles -> IO ProcRetHandles)
-> IO ProcRetHandles -> IO ProcRetHandles
forall a b. (a -> b) -> a -> b
$
(Ptr FD -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr FD -> IO ProcRetHandles) -> IO ProcRetHandles)
-> (Ptr FD -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. (a -> b) -> a -> b
$ \ Ptr FD
pfdStdInput ->
(Ptr FD -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr FD -> IO ProcRetHandles) -> IO ProcRetHandles)
-> (Ptr FD -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. (a -> b) -> a -> b
$ \ Ptr FD
pfdStdOutput ->
(Ptr FD -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr FD -> IO ProcRetHandles) -> IO ProcRetHandles)
-> (Ptr FD -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. (a -> b) -> a -> b
$ \ Ptr FD
pfdStdError ->
(Ptr CString -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CString -> IO ProcRetHandles) -> IO ProcRetHandles)
-> (Ptr CString -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. (a -> b) -> a -> b
$ \ Ptr CString
pFailedDoing ->
([(FilePath, FilePath)]
-> (Ptr CString -> IO ProcRetHandles) -> IO ProcRetHandles)
-> Maybe [(FilePath, FilePath)]
-> (Ptr CString -> IO ProcRetHandles)
-> IO ProcRetHandles
forall a b c.
(a -> (Ptr b -> IO c) -> IO c)
-> Maybe a -> (Ptr b -> IO c) -> IO c
maybeWith [(FilePath, FilePath)]
-> (Ptr CString -> IO ProcRetHandles) -> IO ProcRetHandles
forall a. [(FilePath, FilePath)] -> (Ptr CString -> IO a) -> IO a
withCEnvironment Maybe [(FilePath, FilePath)]
mb_env ((Ptr CString -> IO ProcRetHandles) -> IO ProcRetHandles)
-> (Ptr CString -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. (a -> b) -> a -> b
$ \Ptr CString
pEnv ->
(FilePath -> (CString -> IO ProcRetHandles) -> IO ProcRetHandles)
-> Maybe FilePath
-> (CString -> IO ProcRetHandles)
-> IO ProcRetHandles
forall a b c.
(a -> (Ptr b -> IO c) -> IO c)
-> Maybe a -> (Ptr b -> IO c) -> IO c
maybeWith FilePath -> (CString -> IO ProcRetHandles) -> IO ProcRetHandles
forall a. FilePath -> (CString -> IO a) -> IO a
withFilePath Maybe FilePath
mb_cwd ((CString -> IO ProcRetHandles) -> IO ProcRetHandles)
-> (CString -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. (a -> b) -> a -> b
$ \CString
pWorkDir ->
(GroupID
-> (Ptr GroupID -> IO ProcRetHandles) -> IO ProcRetHandles)
-> Maybe GroupID
-> (Ptr GroupID -> IO ProcRetHandles)
-> IO ProcRetHandles
forall a b c.
(a -> (Ptr b -> IO c) -> IO c)
-> Maybe a -> (Ptr b -> IO c) -> IO c
maybeWith GroupID -> (Ptr GroupID -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. Storable a => a -> (Ptr a -> IO b) -> IO b
with Maybe GroupID
mb_child_group ((Ptr GroupID -> IO ProcRetHandles) -> IO ProcRetHandles)
-> (Ptr GroupID -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. (a -> b) -> a -> b
$ \Ptr GroupID
pChildGroup ->
(UserID -> (Ptr UserID -> IO ProcRetHandles) -> IO ProcRetHandles)
-> Maybe UserID
-> (Ptr UserID -> IO ProcRetHandles)
-> IO ProcRetHandles
forall a b c.
(a -> (Ptr b -> IO c) -> IO c)
-> Maybe a -> (Ptr b -> IO c) -> IO c
maybeWith UserID -> (Ptr UserID -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. Storable a => a -> (Ptr a -> IO b) -> IO b
with Maybe UserID
mb_child_user ((Ptr UserID -> IO ProcRetHandles) -> IO ProcRetHandles)
-> (Ptr UserID -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. (a -> b) -> a -> b
$ \Ptr UserID
pChildUser ->
FilePath -> (CString -> IO ProcRetHandles) -> IO ProcRetHandles
forall a. FilePath -> (CString -> IO a) -> IO a
withFilePath FilePath
cmd ((CString -> IO ProcRetHandles) -> IO ProcRetHandles)
-> (CString -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. (a -> b) -> a -> b
$ \CString
cmdstr ->
(FilePath -> (CString -> IO ProcRetHandles) -> IO ProcRetHandles)
-> [FilePath]
-> ([CString] -> IO ProcRetHandles)
-> IO ProcRetHandles
forall a b res.
(a -> (b -> res) -> res) -> [a] -> ([b] -> res) -> res
withMany FilePath -> (CString -> IO ProcRetHandles) -> IO ProcRetHandles
forall a. FilePath -> (CString -> IO a) -> IO a
withCString [FilePath]
args (([CString] -> IO ProcRetHandles) -> IO ProcRetHandles)
-> ([CString] -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. (a -> b) -> a -> b
$ \[CString]
argstrs -> do
let cstrs :: [CString]
cstrs = CString
cmdstr CString -> [CString] -> [CString]
forall a. a -> [a] -> [a]
: [CString]
argstrs
CString
-> [CString]
-> (Ptr CString -> IO ProcRetHandles)
-> IO ProcRetHandles
forall a b. Storable a => a -> [a] -> (Ptr a -> IO b) -> IO b
withArray0 CString
forall a. Ptr a
nullPtr [CString]
cstrs ((Ptr CString -> IO ProcRetHandles) -> IO ProcRetHandles)
-> (Ptr CString -> IO ProcRetHandles) -> IO ProcRetHandles
forall a b. (a -> b) -> a -> b
$ \Ptr CString
pargs -> do
fdin <- FilePath -> FD -> StdStream -> IO FD
mbFd FilePath
fun FD
fd_stdin StdStream
mb_stdin
fdout <- mbFd fun fd_stdout mb_stdout
fderr <- mbFd fun fd_stderr mb_stderr
when mb_delegate_ctlc
startDelegateControlC
let flags = (if Bool
mb_close_fds then RUN_PROCESS_IN_CLOSE_FDS else 0)
FD -> FD -> FD
forall a. Bits a => a -> a -> a
.|.(if Bool
mb_create_group then RUN_PROCESS_IN_NEW_GROUP else 0)
FD -> FD -> FD
forall a. Bits a => a -> a -> a
.|.(if Bool
mb_detach_console then RUN_PROCESS_DETACHED else 0)
FD -> FD -> FD
forall a. Bits a => a -> a -> a
.|.(if Bool
mb_create_new_console then RUN_PROCESS_NEW_CONSOLE else 0)
FD -> FD -> FD
forall a. Bits a => a -> a -> a
.|.(if Bool
mb_new_session then RUN_PROCESS_NEW_SESSION else 0)
FD -> FD -> FD
forall a. Bits a => a -> a -> a
.|.(if Bool
mb_delegate_ctlc then RESET_INT_QUIT_HANDLERS else 0)
proc_handle <- withMVar runInteractiveProcess_lock $ \()
_ ->
Ptr CString
-> CString
-> Ptr CString
-> FD
-> FD
-> FD
-> Ptr FD
-> Ptr FD
-> Ptr FD
-> Ptr GroupID
-> Ptr UserID
-> FD
-> Ptr CString
-> IO PHANDLE
c_runInteractiveProcess Ptr CString
pargs CString
pWorkDir Ptr CString
pEnv
FD
fdin FD
fdout FD
fderr
Ptr FD
pfdStdInput Ptr FD
pfdStdOutput Ptr FD
pfdStdError
Ptr GroupID
pChildGroup Ptr UserID
pChildUser
FD
flags
Ptr CString
pFailedDoing
when (proc_handle == -1) $ do
cFailedDoing <- peek pFailedDoing
failedDoing <- peekCString cFailedDoing
when mb_delegate_ctlc
stopDelegateControlC
throwErrno (fun ++ ": " ++ failedDoing)
hndStdInput <- mbPipe mb_stdin pfdStdInput WriteMode
hndStdOutput <- mbPipe mb_stdout pfdStdOutput ReadMode
hndStdError <- mbPipe mb_stderr pfdStdError ReadMode
ph <- mkProcessHandle proc_handle mb_delegate_ctlc
return ProcRetHandles { hStdInput = hndStdInput
, hStdOutput = hndStdOutput
, hStdError = hndStdError
, procHandle = ph
}
{-# NOINLINE runInteractiveProcess_lock #-}
runInteractiveProcess_lock :: MVar ()
runInteractiveProcess_lock :: MVar ()
runInteractiveProcess_lock = IO (MVar ()) -> MVar ()
forall a. IO a -> a
unsafePerformIO (IO (MVar ()) -> MVar ()) -> IO (MVar ()) -> MVar ()
forall a b. (a -> b) -> a -> b
$ () -> IO (MVar ())
forall a. a -> IO (MVar a)
newMVar ()
{-# NOINLINE runInteractiveProcess_delegate_ctlc #-}
runInteractiveProcess_delegate_ctlc :: MVar (Maybe (Int, Sig.Handler, Sig.Handler))
runInteractiveProcess_delegate_ctlc :: MVar (Maybe (Int, Handler, Handler))
runInteractiveProcess_delegate_ctlc = IO (MVar (Maybe (Int, Handler, Handler)))
-> MVar (Maybe (Int, Handler, Handler))
forall a. IO a -> a
unsafePerformIO (IO (MVar (Maybe (Int, Handler, Handler)))
-> MVar (Maybe (Int, Handler, Handler)))
-> IO (MVar (Maybe (Int, Handler, Handler)))
-> MVar (Maybe (Int, Handler, Handler))
forall a b. (a -> b) -> a -> b
$ Maybe (Int, Handler, Handler)
-> IO (MVar (Maybe (Int, Handler, Handler)))
forall a. a -> IO (MVar a)
newMVar Maybe (Int, Handler, Handler)
forall a. Maybe a
Nothing
startDelegateControlC :: IO ()
startDelegateControlC :: IO ()
startDelegateControlC =
MVar (Maybe (Int, Handler, Handler))
-> (Maybe (Int, Handler, Handler)
-> IO (Maybe (Int, Handler, Handler)))
-> IO ()
forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ MVar (Maybe (Int, Handler, Handler))
runInteractiveProcess_delegate_ctlc ((Maybe (Int, Handler, Handler)
-> IO (Maybe (Int, Handler, Handler)))
-> IO ())
-> (Maybe (Int, Handler, Handler)
-> IO (Maybe (Int, Handler, Handler)))
-> IO ()
forall a b. (a -> b) -> a -> b
$ \Maybe (Int, Handler, Handler)
delegating -> do
case Maybe (Int, Handler, Handler)
delegating of
Maybe (Int, Handler, Handler)
Nothing -> do
old_int <- FD -> Handler -> Maybe SignalSet -> IO Handler
installHandler FD
sigINT Handler
Ignore Maybe SignalSet
forall a. Maybe a
Nothing
old_quit <- installHandler sigQUIT Ignore Nothing
return (Just (1, old_int, old_quit))
Just (Int
count, Handler
old_int, Handler
old_quit) -> do
let !count' :: Int
count' = Int
count Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
Maybe (Int, Handler, Handler) -> IO (Maybe (Int, Handler, Handler))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ((Int, Handler, Handler) -> Maybe (Int, Handler, Handler)
forall a. a -> Maybe a
Just (Int
count', Handler
old_int, Handler
old_quit))
stopDelegateControlC :: IO ()
stopDelegateControlC :: IO ()
stopDelegateControlC =
MVar (Maybe (Int, Handler, Handler))
-> (Maybe (Int, Handler, Handler)
-> IO (Maybe (Int, Handler, Handler)))
-> IO ()
forall a. MVar a -> (a -> IO a) -> IO ()
modifyMVar_ MVar (Maybe (Int, Handler, Handler))
runInteractiveProcess_delegate_ctlc ((Maybe (Int, Handler, Handler)
-> IO (Maybe (Int, Handler, Handler)))
-> IO ())
-> (Maybe (Int, Handler, Handler)
-> IO (Maybe (Int, Handler, Handler)))
-> IO ()
forall a b. (a -> b) -> a -> b
$ \Maybe (Int, Handler, Handler)
delegating -> do
case Maybe (Int, Handler, Handler)
delegating of
Just (Int
1, Handler
old_int, Handler
old_quit) -> do
_ <- FD -> Handler -> Maybe SignalSet -> IO Handler
installHandler FD
sigINT Handler
old_int Maybe SignalSet
forall a. Maybe a
Nothing
_ <- installHandler sigQUIT old_quit Nothing
return Nothing
Just (Int
count, Handler
old_int, Handler
old_quit) -> do
let !count' :: Int
count' = Int
count Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
Maybe (Int, Handler, Handler) -> IO (Maybe (Int, Handler, Handler))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ((Int, Handler, Handler) -> Maybe (Int, Handler, Handler)
forall a. a -> Maybe a
Just (Int
count', Handler
old_int, Handler
old_quit))
Maybe (Int, Handler, Handler)
Nothing -> Maybe (Int, Handler, Handler) -> IO (Maybe (Int, Handler, Handler))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (Int, Handler, Handler)
forall a. Maybe a
Nothing
endDelegateControlC :: ExitCode -> IO ()
endDelegateControlC :: ExitCode -> IO ()
endDelegateControlC ExitCode
exitCode = do
IO ()
stopDelegateControlC
case ExitCode
exitCode of
ExitFailure Int
n | Int -> Bool
forall {p}. Integral p => p -> Bool
isSigIntQuit Int
n -> AsyncException -> IO ()
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO AsyncException
UserInterrupt
ExitCode
_ -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
where
isSigIntQuit :: p -> Bool
isSigIntQuit p
n = FD
sig FD -> FD -> Bool
forall a. Eq a => a -> a -> Bool
== FD
sigINT Bool -> Bool -> Bool
|| FD
sig FD -> FD -> Bool
forall a. Eq a => a -> a -> Bool
== FD
sigQUIT
where
sig :: FD
sig = p -> FD
forall a b. (Integral a, Num b) => a -> b
fromIntegral (-p
n)
#if defined(wasm32_HOST_ARCH)
c_runInteractiveProcess
:: Ptr CString
-> CString
-> Ptr CString
-> FD
-> FD
-> FD
-> Ptr FD
-> Ptr FD
-> Ptr FD
-> Ptr CGid
-> Ptr CUid
-> CInt
-> Ptr CString
-> IO PHANDLE
c_runInteractiveProcess _ _ _ _ _ _ _ _ _ _ _ _ _ = ioError (ioeSetLocation unsupportedOperation "runInteractiveProcess")
#else
foreign import ccall unsafe "runInteractiveProcess"
c_runInteractiveProcess
:: Ptr CString
-> CString
-> Ptr CString
-> FD
-> FD
-> FD
-> Ptr FD
-> Ptr FD
-> Ptr FD
-> Ptr CGid
-> Ptr CUid
-> CInt
-> Ptr CString
-> IO PHANDLE
#endif
ignoreSignal, defaultSignal :: CLong
ignoreSignal :: CLong
ignoreSignal = CONST_SIG_IGN
defaultSignal :: CLong
defaultSignal = CONST_SIG_DFL
isDefaultSignal :: CLong -> Bool
isDefaultSignal :: CLong -> Bool
isDefaultSignal = (CLong -> CLong -> Bool
forall a. Eq a => a -> a -> Bool
== CLong
defaultSignal)
createPipeInternal :: IO (Handle, Handle)
createPipeInternal :: IO (Handle, Handle)
createPipeInternal = do
(readfd, writefd) <- IO (Fd, Fd)
Posix.createPipe
readh <- Posix.fdToHandle readfd
writeh <- Posix.fdToHandle writefd
return (readh, writeh)
createPipeInternalFd :: IO (FD, FD)
createPipeInternalFd :: IO (FD, FD)
createPipeInternalFd = do
(Fd readfd, Fd writefd) <- IO (Fd, Fd)
Posix.createPipe
return (readfd, writefd)
interruptProcessGroupOfInternal
:: ProcessHandle
-> IO ()
interruptProcessGroupOfInternal :: ProcessHandle -> IO ()
interruptProcessGroupOfInternal ProcessHandle
ph = do
ProcessHandle -> (ProcessHandle__ -> IO ()) -> IO ()
forall a. ProcessHandle -> (ProcessHandle__ -> IO a) -> IO a
withProcessHandle ProcessHandle
ph ((ProcessHandle__ -> IO ()) -> IO ())
-> (ProcessHandle__ -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ProcessHandle__
p_ -> do
case ProcessHandle__
p_ of
OpenExtHandle{} -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
ClosedHandle ExitCode
_ -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
OpenHandle PHANDLE
h -> do
pgid <- PHANDLE -> IO PHANDLE
getProcessGroupIDOf PHANDLE
h
signalProcessGroup sigINT pgid