    {-# LANGUAGE LambdaCase #-}
    {-# LANGUAGE RecordWildCards #-}

    -- | A wrapping of createProcess to provide a more flexible interface.
    module General.Process(
        Buffer, newBuffer, readBuffer,
        process, ProcessOpts(..), Source(..), Destination(..)
        ) where

    import Control.Concurrent.Extra
    import Control.DeepSeq
    import Control.Exception.Extra as C
    import Control.Monad.Extra
    import Data.List.Extra
    import Data.Maybe
    import Foreign.C.Error
    import System.Exit
    import System.IO.Extra
    import System.Info.Extra
    import System.Process
    import System.Time.Extra
    import Data.Unique
    import Data.IORef.Extra
    import qualified Data.ByteString.Char8 as BS
    import qualified Data.ByteString.Lazy as LBS
    import General.Extra
    import Development.Shake.Internal.Errors

    import GHC.IO.Exception (IOErrorType(..), IOException(..))

    ---------------------------------------------------------------------
    -- BUFFER ABSTRACTION

    data Buffer a = Buffer Unique (IORef [a])
    instance Eq (Buffer a) where Buffer Unique
    x IORef [a]
    _ == :: Buffer a -> Buffer a -> Bool
    == Buffer Unique
    y IORef [a]
    _ = Unique
    x Unique -> Unique -> Bool
    forall a. Eq a => a -> a -> Bool
    == Unique
    y
    instance Ord (Buffer a) where compare :: Buffer a -> Buffer a -> Ordering
    compare (Buffer Unique
    x IORef [a]
    _) (Buffer Unique
    y IORef [a]
    _) = Unique -> Unique -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare Unique
    x Unique
    y

    newBuffer :: IO (Buffer a)
    newBuffer :: forall a. IO (Buffer a)
    newBuffer = (Unique -> IORef [a] -> Buffer a)
    -> IO Unique -> IO (IORef [a]) -> IO (Buffer a)
    forall (m :: * -> *) a1 a2 r.
    Monad m =>
    (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
    liftM2 Unique -> IORef [a] -> Buffer a
    forall a. Unique -> IORef [a] -> Buffer a
    Buffer IO Unique
    newUnique ([a] -> IO (IORef [a])
    forall a. a -> IO (IORef a)
    newIORef [])

    addBuffer :: Buffer a -> a -> IO ()
    addBuffer :: forall a. Buffer a -> a -> IO ()
    addBuffer (Buffer Unique
    _ IORef [a]
    ref) a
    x = IORef [a] -> ([a] -> [a]) -> IO ()
    forall a. IORef a -> (a -> a) -> IO ()
    atomicModifyIORef_ IORef [a]
    ref (a
    xa -> [a] -> [a]
    forall a. a -> [a] -> [a]
    :)

    readBuffer :: Buffer a -> IO [a]
    readBuffer :: forall a. Buffer a -> IO [a]
    readBuffer (Buffer Unique
    _ IORef [a]
    ref) = [a] -> [a]
    forall a. [a] -> [a]
    reverse ([a] -> [a]) -> IO [a] -> IO [a]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> IORef [a] -> IO [a]
    forall a. IORef a -> IO a
    readIORef IORef [a]
    ref

    ---------------------------------------------------------------------
    -- OPTIONS

    data Source
        = SrcFile FilePath
        | SrcString String
        | SrcBytes LBS.ByteString
        | SrcInherit

    data Destination
        = DestEcho
        | DestFile FilePath
        | DestString (Buffer String)
        | DestBytes (Buffer BS.ByteString)
          deriving (Destination -> Destination -> Bool
    (Destination -> Destination -> Bool)
    -> (Destination -> Destination -> Bool) -> Eq Destination
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Destination -> Destination -> Bool
    == :: Destination -> Destination -> Bool
    $c/= :: Destination -> Destination -> Bool
    /= :: Destination -> Destination -> Bool
    Eq,Eq Destination
    Eq Destination
    -> (Destination -> Destination -> Ordering)
    -> (Destination -> Destination -> Bool)
    -> (Destination -> Destination -> Bool)
    -> (Destination -> Destination -> Bool)
    -> (Destination -> Destination -> Bool)
    -> (Destination -> Destination -> Destination)
    -> (Destination -> Destination -> Destination)
    -> Ord Destination
    Destination -> Destination -> Bool
    Destination -> Destination -> Ordering
    Destination -> Destination -> Destination
    forall a.
    Eq a
    -> (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: Destination -> Destination -> Ordering
    compare :: Destination -> Destination -> Ordering
    $c< :: Destination -> Destination -> Bool
    < :: Destination -> Destination -> Bool
    $c<= :: Destination -> Destination -> Bool
    <= :: Destination -> Destination -> Bool
    $c> :: Destination -> Destination -> Bool
    > :: Destination -> Destination -> Bool
    $c>= :: Destination -> Destination -> Bool
    >= :: Destination -> Destination -> Bool
    $cmax :: Destination -> Destination -> Destination
    max :: Destination -> Destination -> Destination
    $cmin :: Destination -> Destination -> Destination
    min :: Destination -> Destination -> Destination
    Ord)

    isDestString :: Destination -> Bool
    isDestString DestString{} = Bool
    True; isDestString Destination
    _ = Bool
    False
    isDestBytes :: Destination -> Bool
    isDestBytes  DestBytes{}  = Bool
    True; isDestBytes  Destination
    _ = Bool
    False

    data ProcessOpts = ProcessOpts
        {ProcessOpts -> CmdSpec
    poCommand :: CmdSpec
        ,ProcessOpts -> Maybe String
    poCwd :: Maybe FilePath
        ,ProcessOpts -> Maybe [(String, String)]
    poEnv :: Maybe [(String, String)]
        ,ProcessOpts -> Maybe Double
    poTimeout :: Maybe Double
        ,ProcessOpts -> [Source]
    poStdin :: [Source]
        ,ProcessOpts -> [Destination]
    poStdout :: [Destination]
        ,ProcessOpts -> [Destination]
    poStderr :: [Destination]
        ,ProcessOpts -> Bool
    poAsync :: Bool
        ,ProcessOpts -> Bool
    poCloseFds :: Bool
        ,ProcessOpts -> Bool
    poGroup :: Bool
        }

    ---------------------------------------------------------------------
    -- IMPLEMENTATION

    -- | If two buffers can be replaced by one and a copy, do that (only if they start empty)
    optimiseBuffers :: ProcessOpts -> IO (ProcessOpts, IO ())
    optimiseBuffers :: ProcessOpts -> IO (ProcessOpts, IO ())
    optimiseBuffers po :: ProcessOpts
    po@ProcessOpts{Bool
    [Destination]
    [Source]
    Maybe Double
    Maybe String
    Maybe [(String, String)]
    CmdSpec
    poCommand :: ProcessOpts -> CmdSpec
    poCwd :: ProcessOpts -> Maybe String
    poEnv :: ProcessOpts -> Maybe [(String, String)]
    poTimeout :: ProcessOpts -> Maybe Double
    poStdin :: ProcessOpts -> [Source]
    poStdout :: ProcessOpts -> [Destination]
    poStderr :: ProcessOpts -> [Destination]
    poAsync :: ProcessOpts -> Bool
    poCloseFds :: ProcessOpts -> Bool
    poGroup :: ProcessOpts -> Bool
    poCommand :: CmdSpec
    poCwd :: Maybe String
    poEnv :: Maybe [(String, String)]
    poTimeout :: Maybe Double
    poStdin :: [Source]
    poStdout :: [Destination]
    poStderr :: [Destination]
    poAsync :: Bool
    poCloseFds :: Bool
    poGroup :: Bool
    ..} = (ProcessOpts, IO ()) -> IO (ProcessOpts, IO ())
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (ProcessOpts
    po{poStdout :: [Destination]
    poStdout = [Destination] -> [Destination]
    forall a. Ord a => [a] -> [a]
    nubOrd [Destination]
    poStdout, poStderr :: [Destination]
    poStderr = [Destination] -> [Destination]
    forall a. Ord a => [a] -> [a]
    nubOrd [Destination]
    poStderr}, () -> IO ()
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ())

    stdStream :: (FilePath -> Handle) -> [Destination] -> [Destination] -> StdStream
    stdStream :: (String -> Handle) -> [Destination] -> [Destination] -> StdStream
    stdStream String -> Handle
    _ [Destination
    DestEcho] [Destination]
    _ = StdStream
    Inherit
    stdStream String -> Handle
    file [DestFile String
    x] [Destination]
    other | [Destination]
    other [Destination] -> [Destination] -> Bool
    forall a. Eq a => a -> a -> Bool
    == [String -> Destination
    DestFile String
    x] Bool -> Bool -> Bool
    || String -> Destination
    DestFile String
    x Destination -> [Destination] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `notElem` [Destination]
    other = Handle -> StdStream
    UseHandle (Handle -> StdStream) -> Handle -> StdStream
    forall a b. (a -> b) -> a -> b
    $ String -> Handle
    file String
    x
    stdStream String -> Handle
    _ [Destination]
    _ [Destination]
    _ = StdStream
    CreatePipe

    stdIn :: (FilePath -> Handle) -> [Source] -> (StdStream, Handle -> IO ())
    stdIn :: (String -> Handle) -> [Source] -> (StdStream, Handle -> IO ())
    stdIn String -> Handle
    _ [Source
    SrcInherit] = (StdStream
    Inherit, IO () -> Handle -> IO ()
    forall a b. a -> b -> a
    const (IO () -> Handle -> IO ()) -> IO () -> Handle -> IO ()
    forall a b. (a -> b) -> a -> b
    $ () -> IO ()
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ())
    stdIn String -> Handle
    file [SrcFile String
    x] = (Handle -> StdStream
    UseHandle (Handle -> StdStream) -> Handle -> StdStream
    forall a b. (a -> b) -> a -> b
    $ String -> Handle
    file String
    x, IO () -> Handle -> IO ()
    forall a b. a -> b -> a
    const (IO () -> Handle -> IO ()) -> IO () -> Handle -> IO ()
    forall a b. (a -> b) -> a -> b
    $ () -> IO ()
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ())
    stdIn String -> Handle
    file [Source]
    src = (,) StdStream
    CreatePipe ((Handle -> IO ()) -> (StdStream, Handle -> IO ()))
    -> (Handle -> IO ()) -> (StdStream, Handle -> IO ())
    forall a b. (a -> b) -> a -> b
    $ \Handle
    h -> IO () -> IO ()
    ignoreSigPipe (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ do
        [Source] -> (Source -> IO ()) -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    t a -> (a -> m b) -> m ()
    forM_ [Source]
    src ((Source -> IO ()) -> IO ()) -> (Source -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \case
            SrcString String
    x -> Handle -> String -> IO ()
    hPutStr Handle
    h String
    x
            SrcBytes ByteString
    x -> Handle -> ByteString -> IO ()
    LBS.hPutStr Handle
    h ByteString
    x
            SrcFile String
    x -> Handle -> ByteString -> IO ()
    LBS.hPutStr Handle
    h (ByteString -> IO ()) -> IO ByteString -> IO ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Handle -> IO ByteString
    LBS.hGetContents (String -> Handle
    file String
    x)
            Source
    SrcInherit -> () -> IO ()
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure () -- Can't both inherit and set it
        Handle -> IO ()
    hClose Handle
    h

    ignoreSigPipe :: IO () -> IO ()
    ignoreSigPipe :: IO () -> IO ()
    ignoreSigPipe = (IOException -> IO ()) -> IO () -> IO ()
    forall a. (IOException -> IO a) -> IO a -> IO a
    handleIO ((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 CInt
    ioe_errno=Just CInt
    ioe} | CInt -> Errno
    Errno CInt
    ioe Errno -> Errno -> Bool
    forall a. Eq a => a -> a -> Bool
    == Errno
    ePIPE -> () -> IO ()
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()
        IOException
    _ -> IOException -> IO ()
    forall e a. Exception e => e -> IO a
    throwIO IOException
    e

    withExceptions :: IO () -> IO a -> IO a
    withExceptions :: forall a. IO () -> IO a -> IO a
    withExceptions IO ()
    stop IO a
    go = do
        Barrier (Either SomeException a)
    bar <- IO (Barrier (Either SomeException a))
    forall a. IO (Barrier a)
    newBarrier
        Either SomeException a
    v <- ((forall a. IO a -> IO a) -> IO (Either SomeException a))
    -> IO (Either SomeException a)
    forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
    mask (((forall a. IO a -> IO a) -> IO (Either SomeException a))
     -> IO (Either SomeException a))
    -> ((forall a. IO a -> IO a) -> IO (Either SomeException a))
    -> IO (Either SomeException a)
    forall a b. (a -> b) -> a -> b
    $ \forall a. IO a -> IO a
    unmask -> do
            IO a -> (Either SomeException a -> IO ()) -> IO ThreadId
    forall a. IO a -> (Either SomeException a -> IO ()) -> IO ThreadId
    forkFinally (IO a -> IO a
    forall a. IO a -> IO a
    unmask IO a
    go) ((Either SomeException a -> IO ()) -> IO ThreadId)
    -> (Either SomeException a -> IO ()) -> IO ThreadId
    forall a b. (a -> b) -> a -> b
    $ Barrier (Either SomeException a) -> Either SomeException a -> IO ()
    forall a. Partial => Barrier a -> a -> IO ()
    signalBarrier Barrier (Either SomeException a)
    bar
            IO (Either SomeException a) -> IO (Either SomeException a)
    forall a. IO a -> IO a
    unmask (Barrier (Either SomeException a) -> IO (Either SomeException a)
    forall a. Barrier a -> IO a
    waitBarrier Barrier (Either SomeException a)
    bar) IO (Either SomeException a)
    -> IO (Either SomeException a) -> IO (Either SomeException a)
    forall a b. IO a -> IO b -> IO a
    `onException` do
                IO () -> IO ThreadId
    forkIO IO ()
    stop
                Barrier (Either SomeException a) -> IO (Either SomeException a)
    forall a. Barrier a -> IO a
    waitBarrier Barrier (Either SomeException a)
    bar
        (SomeException -> IO a)
    -> (a -> IO a) -> Either SomeException a -> IO a
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either SomeException -> IO a
    forall e a. Exception e => e -> IO a
    throwIO a -> IO a
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Either SomeException a
    v

    withTimeout :: Maybe Double -> IO () -> IO a -> IO a
    withTimeout :: forall a. Maybe Double -> IO () -> IO a -> IO a
    withTimeout Maybe Double
    Nothing IO ()
    _ IO a
    go = IO a
    go
    withTimeout (Just Double
    s) IO ()
    stop IO a
    go = IO ThreadId -> (ThreadId -> IO ()) -> (ThreadId -> IO a) -> IO a
    forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
    bracket (IO () -> IO ThreadId
    forkIO (IO () -> IO ThreadId) -> IO () -> IO ThreadId
    forall a b. (a -> b) -> a -> b
    $ Double -> IO ()
    sleep Double
    s IO () -> IO () -> IO ()
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> IO ()
    stop) ThreadId -> IO ()
    killThread ((ThreadId -> IO a) -> IO a) -> (ThreadId -> IO a) -> IO a
    forall a b. (a -> b) -> a -> b
    $ IO a -> ThreadId -> IO a
    forall a b. a -> b -> a
    const IO a
    go

    cmdSpec :: CmdSpec -> CreateProcess
    cmdSpec :: CmdSpec -> CreateProcess
    cmdSpec (ShellCommand String
    x) = String -> CreateProcess
    shell String
    x
    cmdSpec (RawCommand String
    x [String]
    xs) = String -> [String] -> CreateProcess
    proc String
    x [String]
    xs

    forkWait :: IO a -> IO (IO a)
    forkWait :: forall a. IO a -> IO (IO a)
    forkWait IO a
    a = do
        MVar (Either SomeException a)
    res <- IO (MVar (Either SomeException a))
    forall a. IO (MVar a)
    newEmptyMVar
        ThreadId
    _ <- ((forall a. IO a -> IO a) -> IO ThreadId) -> IO ThreadId
    forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
    mask (((forall a. IO a -> IO a) -> IO ThreadId) -> IO ThreadId)
    -> ((forall a. IO a -> IO a) -> IO ThreadId) -> IO ThreadId
    forall a b. (a -> b) -> a -> b
    $ \forall a. IO a -> IO a
    restore -> IO () -> IO ThreadId
    forkIO (IO () -> IO ThreadId) -> IO () -> IO ThreadId
    forall a b. (a -> b) -> a -> b
    $ IO a -> IO (Either SomeException a)
    forall a. IO a -> IO (Either SomeException a)
    try_ (IO a -> IO a
    forall a. IO a -> IO a
    restore IO a
    a) IO (Either SomeException a)
    -> (Either SomeException a -> 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 a) -> Either SomeException a -> IO ()
    forall a. MVar a -> a -> IO ()
    putMVar MVar (Either SomeException a)
    res
        IO a -> IO (IO a)
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (IO a -> IO (IO a)) -> IO a -> IO (IO a)
    forall a b. (a -> b) -> a -> b
    $ MVar (Either SomeException a) -> IO (Either SomeException a)
    forall a. MVar a -> IO a
    takeMVar MVar (Either SomeException a)
    res IO (Either SomeException a)
    -> (Either SomeException a -> IO a) -> IO a
    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 a)
    -> (a -> IO a) -> Either SomeException a -> IO a
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either SomeException -> IO a
    forall e a. Exception e => e -> IO a
    throwIO a -> IO a
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure

    abort :: Bool -> ProcessHandle -> IO ()
    abort :: Bool -> ProcessHandle -> IO ()
    abort Bool
    poGroup ProcessHandle
    pid = do
        Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when Bool
    poGroup (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ do
            ProcessHandle -> IO ()
    interruptProcessGroupOf ProcessHandle
    pid
            Double -> IO ()
    sleep Double
    3 -- give the process a few seconds grace period to die nicely
        ProcessHandle -> IO ()
    terminateProcess ProcessHandle
    pid

    withFiles :: IOMode -> [FilePath] -> ((FilePath -> Handle) -> IO a) -> IO a
    withFiles :: forall a.
    IOMode -> [String] -> ((String -> Handle) -> IO a) -> IO a
    withFiles IOMode
    mode [String]
    files (String -> Handle) -> IO a
    act = [(Handle -> IO a) -> IO a] -> ([Handle] -> IO a) -> IO a
    forall a r. [(a -> r) -> r] -> ([a] -> r) -> r
    withs ((String -> (Handle -> IO a) -> IO a)
    -> [String] -> [(Handle -> IO a) -> IO a]
    forall a b. (a -> b) -> [a] -> [b]
    map (String -> IOMode -> (Handle -> IO a) -> IO a
    forall r. String -> IOMode -> (Handle -> IO r) -> IO r
    `withFile` IOMode
    mode) [String]
    files) (([Handle] -> IO a) -> IO a) -> ([Handle] -> IO a) -> IO a
    forall a b. (a -> b) -> a -> b
    $ \[Handle]
    handles ->
        (String -> Handle) -> IO a
    act ((String -> Handle) -> IO a) -> (String -> Handle) -> IO a
    forall a b. (a -> b) -> a -> b
    $ \String
    x -> Maybe Handle -> Handle
    forall a. Partial => Maybe a -> a
    fromJust (Maybe Handle -> Handle) -> Maybe Handle -> Handle
    forall a b. (a -> b) -> a -> b
    $ String -> [(String, Handle)] -> Maybe Handle
    forall a b. Eq a => a -> [(a, b)] -> Maybe b
    lookup String
    x ([(String, Handle)] -> Maybe Handle)
    -> [(String, Handle)] -> Maybe Handle
    forall a b. (a -> b) -> a -> b
    $ [String] -> [Handle] -> [(String, Handle)]
    forall a b. Partial => [a] -> [b] -> [(a, b)]
    zipExact [String]
    files [Handle]
    handles

    -- General approach taken from readProcessWithExitCode
    process :: ProcessOpts -> IO (ProcessHandle, ExitCode)
    process :: ProcessOpts -> IO (ProcessHandle, ExitCode)
    process ProcessOpts
    po = do
        (ProcessOpts{Bool
    [Destination]
    [Source]
    Maybe Double
    Maybe String
    Maybe [(String, String)]
    CmdSpec
    poCommand :: ProcessOpts -> CmdSpec
    poCwd :: ProcessOpts -> Maybe String
    poEnv :: ProcessOpts -> Maybe [(String, String)]
    poTimeout :: ProcessOpts -> Maybe Double
    poStdin :: ProcessOpts -> [Source]
    poStdout :: ProcessOpts -> [Destination]
    poStderr :: ProcessOpts -> [Destination]
    poAsync :: ProcessOpts -> Bool
    poCloseFds :: ProcessOpts -> Bool
    poGroup :: ProcessOpts -> Bool
    poCommand :: CmdSpec
    poCwd :: Maybe String
    poEnv :: Maybe [(String, String)]
    poTimeout :: Maybe Double
    poStdin :: [Source]
    poStdout :: [Destination]
    poStderr :: [Destination]
    poAsync :: Bool
    poCloseFds :: Bool
    poGroup :: Bool
    ..}, IO ()
    flushBuffers) <- ProcessOpts -> IO (ProcessOpts, IO ())
    optimiseBuffers ProcessOpts
    po
        let outFiles :: [String]
    outFiles = [String] -> [String]
    forall a. Ord a => [a] -> [a]
    nubOrd [String
    x | DestFile String
    x <- [Destination]
    poStdout [Destination] -> [Destination] -> [Destination]
    forall a. [a] -> [a] -> [a]
    ++ [Destination]
    poStderr]
        let inFiles :: [String]
    inFiles = [String] -> [String]
    forall a. Ord a => [a] -> [a]
    nubOrd [String
    x | SrcFile String
    x <- [Source]
    poStdin]
        IOMode
    -> [String]
    -> ((String -> Handle) -> IO (ProcessHandle, ExitCode))
    -> IO (ProcessHandle, ExitCode)
    forall a.
    IOMode -> [String] -> ((String -> Handle) -> IO a) -> IO a
    withFiles IOMode
    WriteMode [String]
    outFiles (((String -> Handle) -> IO (ProcessHandle, ExitCode))
     -> IO (ProcessHandle, ExitCode))
    -> ((String -> Handle) -> IO (ProcessHandle, ExitCode))
    -> IO (ProcessHandle, ExitCode)
    forall a b. (a -> b) -> a -> b
    $ \String -> Handle
    outHandle -> IOMode
    -> [String]
    -> ((String -> Handle) -> IO (ProcessHandle, ExitCode))
    -> IO (ProcessHandle, ExitCode)
    forall a.
    IOMode -> [String] -> ((String -> Handle) -> IO a) -> IO a
    withFiles IOMode
    ReadMode [String]
    inFiles (((String -> Handle) -> IO (ProcessHandle, ExitCode))
     -> IO (ProcessHandle, ExitCode))
    -> ((String -> Handle) -> IO (ProcessHandle, ExitCode))
    -> IO (ProcessHandle, ExitCode)
    forall a b. (a -> b) -> a -> b
    $ \String -> Handle
    inHandle -> do
            let cp :: CreateProcess
    cp = (CmdSpec -> CreateProcess
    cmdSpec CmdSpec
    poCommand){cwd :: Maybe String
    cwd = Maybe String
    poCwd, env :: Maybe [(String, String)]
    env = Maybe [(String, String)]
    poEnv, create_group :: Bool
    create_group = Bool
    poGroup, close_fds :: Bool
    close_fds = Bool
    poCloseFds
                     ,std_in :: StdStream
    std_in = (StdStream, Handle -> IO ()) -> StdStream
    forall a b. (a, b) -> a
    fst ((StdStream, Handle -> IO ()) -> StdStream)
    -> (StdStream, Handle -> IO ()) -> StdStream
    forall a b. (a -> b) -> a -> b
    $ (String -> Handle) -> [Source] -> (StdStream, Handle -> IO ())
    stdIn String -> Handle
    inHandle [Source]
    poStdin
                     ,std_out :: StdStream
    std_out = (String -> Handle) -> [Destination] -> [Destination] -> StdStream
    stdStream String -> Handle
    outHandle [Destination]
    poStdout [Destination]
    poStderr, std_err :: StdStream
    std_err = (String -> Handle) -> [Destination] -> [Destination] -> StdStream
    stdStream String -> Handle
    outHandle [Destination]
    poStderr [Destination]
    poStdout}
            CreateProcess
    -> (Maybe Handle
        -> Maybe Handle
        -> Maybe Handle
        -> ProcessHandle
        -> IO (ProcessHandle, ExitCode))
    -> IO (ProcessHandle, ExitCode)
    forall a.
    CreateProcess
    -> (Maybe Handle
        -> Maybe Handle -> Maybe Handle -> ProcessHandle -> IO a)
    -> IO a
    withCreateProcessCompat CreateProcess
    cp ((Maybe Handle
      -> Maybe Handle
      -> Maybe Handle
      -> ProcessHandle
      -> IO (ProcessHandle, ExitCode))
     -> IO (ProcessHandle, ExitCode))
    -> (Maybe Handle
        -> Maybe Handle
        -> Maybe Handle
        -> ProcessHandle
        -> IO (ProcessHandle, ExitCode))
    -> IO (ProcessHandle, ExitCode)
    forall a b. (a -> b) -> a -> b
    $ \Maybe Handle
    inh Maybe Handle
    outh Maybe Handle
    errh ProcessHandle
    pid ->
                Maybe Double
    -> IO ()
    -> IO (ProcessHandle, ExitCode)
    -> IO (ProcessHandle, ExitCode)
    forall a. Maybe Double -> IO () -> IO a -> IO a
    withTimeout Maybe Double
    poTimeout (Bool -> ProcessHandle -> IO ()
    abort Bool
    poGroup ProcessHandle
    pid) (IO (ProcessHandle, ExitCode) -> IO (ProcessHandle, ExitCode))
    -> IO (ProcessHandle, ExitCode) -> IO (ProcessHandle, ExitCode)
    forall a b. (a -> b) -> a -> b
    $ IO ()
    -> IO (ProcessHandle, ExitCode) -> IO (ProcessHandle, ExitCode)
    forall a. IO () -> IO a -> IO a
    withExceptions (Bool -> ProcessHandle -> IO ()
    abort Bool
    poGroup ProcessHandle
    pid) (IO (ProcessHandle, ExitCode) -> IO (ProcessHandle, ExitCode))
    -> IO (ProcessHandle, ExitCode) -> IO (ProcessHandle, ExitCode)
    forall a b. (a -> b) -> a -> b
    $ do

                    let streams :: [(Handle, Handle, [Destination])]
    streams = [(Handle
    outh, Handle
    stdout, [Destination]
    poStdout) | Just Handle
    outh <- [Maybe Handle
    outh], StdStream
    CreatePipe <- [CreateProcess -> StdStream
    std_out CreateProcess
    cp]] [(Handle, Handle, [Destination])]
    -> [(Handle, Handle, [Destination])]
    -> [(Handle, Handle, [Destination])]
    forall a. [a] -> [a] -> [a]
    ++
                                  [(Handle
    errh, Handle
    stderr, [Destination]
    poStderr) | Just Handle
    errh <- [Maybe Handle
    errh], StdStream
    CreatePipe <- [CreateProcess -> StdStream
    std_err CreateProcess
    cp]]
                    [IO ()]
    wait <- [(Handle, Handle, [Destination])]
    -> ((Handle, Handle, [Destination]) -> IO (IO ())) -> IO [IO ()]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    t a -> (a -> m b) -> m (t b)
    forM [(Handle, Handle, [Destination])]
    streams (((Handle, Handle, [Destination]) -> IO (IO ())) -> IO [IO ()])
    -> ((Handle, Handle, [Destination]) -> IO (IO ())) -> IO [IO ()]
    forall a b. (a -> b) -> a -> b
    $ \(Handle
    h, Handle
    hh, [Destination]
    dest) -> do
                        -- no point tying the streams together if one is being streamed directly
                        let isTied :: Bool
    isTied = Bool -> Bool
    not ([Destination]
    poStdout [Destination] -> [Destination] -> Bool
    forall a. Eq a => [a] -> [a] -> Bool
    `disjoint` [Destination]
    poStderr) Bool -> Bool -> Bool
    && [(Handle, Handle, [Destination])] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [(Handle, Handle, [Destination])]
    streams Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    2
                        let isBinary :: Bool
    isBinary = (Destination -> Bool) -> [Destination] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any Destination -> Bool
    isDestBytes [Destination]
    dest Bool -> Bool -> Bool
    || Bool -> Bool
    not ((Destination -> Bool) -> [Destination] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any Destination -> Bool
    isDestString [Destination]
    dest)
                        Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when Bool
    isTied (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Handle -> BufferMode -> IO ()
    hSetBuffering Handle
    h BufferMode
    LineBuffering
                        Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (Destination
    DestEcho Destination -> [Destination] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Destination]
    dest) (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ do
                            BufferMode
    buf <- Handle -> IO BufferMode
    hGetBuffering Handle
    hh
                            case BufferMode
    buf of
                                BlockBuffering{} -> () -> IO ()
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()
                                BufferMode
    _ -> Handle -> BufferMode -> IO ()
    hSetBuffering Handle
    h BufferMode
    buf

                        if Bool
    isBinary then do
                            Handle -> Bool -> IO ()
    hSetBinaryMode Handle
    h Bool
    True
                            [ByteString -> IO ()]
    dest<- [ByteString -> IO ()] -> IO [ByteString -> IO ()]
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ([ByteString -> IO ()] -> IO [ByteString -> IO ()])
    -> [ByteString -> IO ()] -> IO [ByteString -> IO ()]
    forall a b. (a -> b) -> a -> b
    $ ((Destination -> ByteString -> IO ())
     -> [Destination] -> [ByteString -> IO ()])
    -> [Destination]
    -> (Destination -> ByteString -> IO ())
    -> [ByteString -> IO ()]
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip (Destination -> ByteString -> IO ())
    -> [Destination] -> [ByteString -> IO ()]
    forall a b. (a -> b) -> [a] -> [b]
    map [Destination]
    dest ((Destination -> ByteString -> IO ()) -> [ByteString -> IO ()])
    -> (Destination -> ByteString -> IO ()) -> [ByteString -> IO ()]
    forall a b. (a -> b) -> a -> b
    $ \case
                                Destination
    DestEcho -> Handle -> ByteString -> IO ()
    BS.hPut Handle
    hh
                                DestFile String
    x -> Handle -> ByteString -> IO ()
    BS.hPut (String -> Handle
    outHandle String
    x)
                                DestString Buffer String
    x -> Buffer String -> String -> IO ()
    forall a. Buffer a -> a -> IO ()
    addBuffer Buffer String
    x (String -> IO ()) -> (ByteString -> String) -> ByteString -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (if Bool
    isWindows then String -> String -> String -> String
    forall a. Eq a => [a] -> [a] -> [a] -> [a]
    replace String
    "\r\n" String
    "\n" else String -> String
    forall a. a -> a
    id) (String -> String)
    -> (ByteString -> String) -> ByteString -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> String
    BS.unpack
                                DestBytes Buffer ByteString
    x -> Buffer ByteString -> ByteString -> IO ()
    forall a. Buffer a -> a -> IO ()
    addBuffer Buffer ByteString
    x
                            IO () -> IO (IO ())
    forall a. IO a -> IO (IO a)
    forkWait (IO () -> IO (IO ())) -> IO () -> IO (IO ())
    forall a b. (a -> b) -> a -> b
    $ IO Bool -> IO ()
    forall (m :: * -> *). Monad m => m Bool -> m ()
    whileM (IO Bool -> IO ()) -> IO Bool -> IO ()
    forall a b. (a -> b) -> a -> b
    $ do
                                ByteString
    src <- Handle -> Int -> IO ByteString
    BS.hGetSome Handle
    h Int
    4096
                                ((ByteString -> IO ()) -> IO ()) -> [ByteString -> IO ()] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ ((ByteString -> IO ()) -> ByteString -> IO ()
    forall a b. (a -> b) -> a -> b
    $ ByteString
    src) [ByteString -> IO ()]
    dest
                                IO Bool -> IO Bool
    forall (m :: * -> *). Functor m => m Bool -> m Bool
    notM (IO Bool -> IO Bool) -> IO Bool -> IO Bool
    forall a b. (a -> b) -> a -> b
    $ Handle -> IO Bool
    hIsEOF Handle
    h
                         else if Bool
    isTied then do
                            [String -> IO ()]
    dest<- [String -> IO ()] -> IO [String -> IO ()]
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ([String -> IO ()] -> IO [String -> IO ()])
    -> [String -> IO ()] -> IO [String -> IO ()]
    forall a b. (a -> b) -> a -> b
    $ ((Destination -> String -> IO ())
     -> [Destination] -> [String -> IO ()])
    -> [Destination]
    -> (Destination -> String -> IO ())
    -> [String -> IO ()]
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip (Destination -> String -> IO ())
    -> [Destination] -> [String -> IO ()]
    forall a b. (a -> b) -> [a] -> [b]
    map [Destination]
    dest ((Destination -> String -> IO ()) -> [String -> IO ()])
    -> (Destination -> String -> IO ()) -> [String -> IO ()]
    forall a b. (a -> b) -> a -> b
    $ \case
                                Destination
    DestEcho -> Handle -> String -> IO ()
    hPutStrLn Handle
    hh
                                DestFile String
    x -> Handle -> String -> IO ()
    hPutStrLn (String -> Handle
    outHandle String
    x)
                                DestString Buffer String
    x -> Buffer String -> String -> IO ()
    forall a. Buffer a -> a -> IO ()
    addBuffer Buffer String
    x (String -> IO ()) -> (String -> String) -> String -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    "\n")
                                DestBytes{} -> SomeException -> String -> IO ()
    forall a. SomeException -> a
    throwImpure (SomeException -> String -> IO ())
    -> SomeException -> String -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Partial => String -> SomeException
    String -> SomeException
    errorInternal String
    "Not reachable due to isBinary condition"
                            IO () -> IO (IO ())
    forall a. IO a -> IO (IO a)
    forkWait (IO () -> IO (IO ())) -> IO () -> IO (IO ())
    forall a b. (a -> b) -> a -> b
    $ IO Bool -> IO ()
    forall (m :: * -> *). Monad m => m Bool -> m ()
    whileM (IO Bool -> IO ()) -> IO Bool -> IO ()
    forall a b. (a -> b) -> a -> b
    $
                                IO Bool -> IO Bool -> IO Bool -> IO Bool
    forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
    ifM (Handle -> IO Bool
    hIsEOF Handle
    h) (Bool -> IO Bool
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Bool
    False) (IO Bool -> IO Bool) -> IO Bool -> IO Bool
    forall a b. (a -> b) -> a -> b
    $ do
                                    String
    src <- Handle -> IO String
    hGetLine Handle
    h
                                    ((String -> IO ()) -> IO ()) -> [String -> IO ()] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ ((String -> IO ()) -> String -> IO ()
    forall a b. (a -> b) -> a -> b
    $ String
    src) [String -> IO ()]
    dest
                                    Bool -> IO Bool
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Bool
    True
                         else do
                            String
    src <- Handle -> IO String
    hGetContents Handle
    h
                            IO ()
    wait1 <- IO () -> IO (IO ())
    forall a. IO a -> IO (IO a)
    forkWait (IO () -> IO (IO ())) -> IO () -> IO (IO ())
    forall a b. (a -> b) -> a -> b
    $ () -> IO ()
    forall a. a -> IO a
    C.evaluate (() -> IO ()) -> () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ String -> ()
    forall a. NFData a => a -> ()
    rnf String
    src
                            [IO ()]
    waits <- [Destination] -> (Destination -> IO (IO ())) -> IO [IO ()]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    t a -> (a -> m b) -> m (t b)
    forM [Destination]
    dest ((Destination -> IO (IO ())) -> IO [IO ()])
    -> (Destination -> IO (IO ())) -> IO [IO ()]
    forall a b. (a -> b) -> a -> b
    $ \case
                                Destination
    DestEcho -> IO () -> IO (IO ())
    forall a. IO a -> IO (IO a)
    forkWait (IO () -> IO (IO ())) -> IO () -> IO (IO ())
    forall a b. (a -> b) -> a -> b
    $ Handle -> String -> IO ()
    hPutStr Handle
    hh String
    src
                                DestFile String
    x -> IO () -> IO (IO ())
    forall a. IO a -> IO (IO a)
    forkWait (IO () -> IO (IO ())) -> IO () -> IO (IO ())
    forall a b. (a -> b) -> a -> b
    $ Handle -> String -> IO ()
    hPutStr (String -> Handle
    outHandle String
    x) String
    src
                                DestString Buffer String
    x -> do Buffer String -> String -> IO ()
    forall a. Buffer a -> a -> IO ()
    addBuffer Buffer String
    x String
    src; IO () -> IO (IO ())
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (IO () -> IO (IO ())) -> IO () -> IO (IO ())
    forall a b. (a -> b) -> a -> b
    $ () -> IO ()
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()
                                DestBytes{} -> SomeException -> IO (IO ())
    forall a. SomeException -> a
    throwImpure (SomeException -> IO (IO ())) -> SomeException -> IO (IO ())
    forall a b. (a -> b) -> a -> b
    $ Partial => String -> SomeException
    String -> SomeException
    errorInternal String
    "Not reachable due to isBinary condition"
                            IO () -> IO (IO ())
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (IO () -> IO (IO ())) -> IO () -> IO (IO ())
    forall a b. (a -> b) -> a -> b
    $ [IO ()] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a.
    (Foldable t, Monad m) =>
    t (m a) -> m ()
    sequence_ ([IO ()] -> IO ()) -> [IO ()] -> IO ()
    forall a b. (a -> b) -> a -> b
    $ IO ()
    wait1 IO () -> [IO ()] -> [IO ()]
    forall a. a -> [a] -> [a]
    : [IO ()]
    waits

                    Maybe Handle -> (Handle -> IO ()) -> IO ()
    forall (m :: * -> *) a.
    Applicative m =>
    Maybe a -> (a -> m ()) -> m ()
    whenJust Maybe Handle
    inh ((Handle -> IO ()) -> IO ()) -> (Handle -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ (StdStream, Handle -> IO ()) -> Handle -> IO ()
    forall a b. (a, b) -> b
    snd ((StdStream, Handle -> IO ()) -> Handle -> IO ())
    -> (StdStream, Handle -> IO ()) -> Handle -> IO ()
    forall a b. (a -> b) -> a -> b
    $ (String -> Handle) -> [Source] -> (StdStream, Handle -> IO ())
    stdIn String -> Handle
    inHandle [Source]
    poStdin
                    if Bool
    poAsync then
                        (ProcessHandle, ExitCode) -> IO (ProcessHandle, ExitCode)
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (ProcessHandle
    pid, ExitCode
    ExitSuccess)
                     else do
                        [IO ()] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a.
    (Foldable t, Monad m) =>
    t (m a) -> m ()
    sequence_ [IO ()]
    wait
                        IO ()
    flushBuffers
                        ExitCode
    res <- ProcessHandle -> IO ExitCode
    waitForProcess ProcessHandle
    pid
                        Maybe Handle -> (Handle -> IO ()) -> IO ()
    forall (m :: * -> *) a.
    Applicative m =>
    Maybe a -> (a -> m ()) -> m ()
    whenJust Maybe Handle
    outh Handle -> IO ()
    hClose
                        Maybe Handle -> (Handle -> IO ()) -> IO ()
    forall (m :: * -> *) a.
    Applicative m =>
    Maybe a -> (a -> m ()) -> m ()
    whenJust Maybe Handle
    errh Handle -> IO ()
    hClose
                        (ProcessHandle, ExitCode) -> IO (ProcessHandle, ExitCode)
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (ProcessHandle
    pid, ExitCode
    res)

    ---------------------------------------------------------------------
    -- COMPATIBILITY

    -- available in process-1.4.3.0, GHC ??? (Nov 2015)
    -- logic copied directly (apart from Ctrl-C handling magic using internal pieces)
    withCreateProcessCompat :: CreateProcess -> (Maybe Handle -> Maybe Handle -> Maybe Handle -> ProcessHandle -> IO a) -> IO a
    withCreateProcessCompat :: forall a.
    CreateProcess
    -> (Maybe Handle
        -> Maybe Handle -> Maybe Handle -> ProcessHandle -> IO a)
    -> IO a
    withCreateProcessCompat CreateProcess
    cp Maybe Handle
    -> Maybe Handle -> Maybe Handle -> ProcessHandle -> IO a
    act = IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
    -> ((Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
        -> IO ThreadId)
    -> ((Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
        -> IO a)
    -> IO a
    forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
    bracketOnError (CreateProcess
    -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
    createProcess CreateProcess
    cp) (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
    -> IO ThreadId
    cleanup
        (\(Maybe Handle
    m_in, Maybe Handle
    m_out, Maybe Handle
    m_err, ProcessHandle
    ph) -> Maybe Handle
    -> Maybe Handle -> Maybe Handle -> ProcessHandle -> IO a
    act Maybe Handle
    m_in Maybe Handle
    m_out Maybe Handle
    m_err ProcessHandle
    ph)
        where
            cleanup :: (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
    -> IO ThreadId
    cleanup (Maybe Handle
    inh, Maybe Handle
    outh, Maybe Handle
    errh, ProcessHandle
    pid) = do
                ProcessHandle -> IO ()
    terminateProcess ProcessHandle
    pid
                Maybe Handle -> (Handle -> IO ()) -> IO ()
    forall (m :: * -> *) a.
    Applicative m =>
    Maybe a -> (a -> m ()) -> m ()
    whenJust Maybe Handle
    inh ((Handle -> IO ()) -> IO ()) -> (Handle -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ IO () -> IO ()
    ignoreSigPipe (IO () -> IO ()) -> (Handle -> IO ()) -> Handle -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle -> IO ()
    hClose
                Maybe Handle -> (Handle -> IO ()) -> IO ()
    forall (m :: * -> *) a.
    Applicative m =>
    Maybe a -> (a -> m ()) -> m ()
    whenJust Maybe Handle
    outh Handle -> IO ()
    hClose
                Maybe Handle -> (Handle -> IO ()) -> IO ()
    forall (m :: * -> *) a.
    Applicative m =>
    Maybe a -> (a -> m ()) -> m ()
    whenJust Maybe Handle
    errh Handle -> IO ()
    hClose
                IO () -> IO ThreadId
    forkIO (IO () -> IO ThreadId) -> IO () -> IO ThreadId
    forall a b. (a -> b) -> a -> b
    $ IO ExitCode -> IO ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (IO ExitCode -> IO ()) -> IO ExitCode -> IO ()
    forall a b. (a -> b) -> a -> b
    $ ProcessHandle -> IO ExitCode
    waitForProcess ProcessHandle
    pid