summaryrefslogtreecommitdiff
path: root/Utility/Process.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Utility/Process.hs')
-rw-r--r--Utility/Process.hs58
1 files changed, 45 insertions, 13 deletions
diff --git a/Utility/Process.hs b/Utility/Process.hs
index 8ea632120..398e8a352 100644
--- a/Utility/Process.hs
+++ b/Utility/Process.hs
@@ -44,8 +44,10 @@ import qualified Control.Exception as E
import Control.Monad
#ifndef mingw32_HOST_OS
import System.Posix.IO
-import Data.Maybe
+#else
+import Control.Applicative
#endif
+import Data.Maybe
import Utility.Misc
import Utility.Exception
@@ -72,17 +74,17 @@ readProcessEnv cmd args environ =
, env = environ
}
-{- Writes a string to a process on its stdin,
+{- Runs an action to write to a process on its stdin,
- returns its output, and also allows specifying the environment.
-}
writeReadProcessEnv
:: FilePath
-> [String]
-> Maybe [(String, String)]
- -> String
+ -> (Maybe (Handle -> IO ()))
-> (Maybe (Handle -> IO ()))
-> IO String
-writeReadProcessEnv cmd args environ input adjusthandle = do
+writeReadProcessEnv cmd args environ writestdin adjusthandle = do
(Just inh, Just outh, _, pid) <- createProcess p
maybe (return ()) (\a -> a inh) adjusthandle
@@ -94,7 +96,7 @@ writeReadProcessEnv cmd args environ input adjusthandle = do
_ <- forkIO $ E.evaluate (length output) >> putMVar outMVar ()
-- now write and flush any input
- when (not (null input)) $ do hPutStr inh input; hFlush inh
+ maybe (return ()) (\a -> a inh >> hFlush inh) writestdin
hClose inh -- done with stdin
-- wait on the output
@@ -161,6 +163,8 @@ createBackgroundProcess p a = a =<< createProcess p
- whether it succeeded or failed. -}
processTranscript :: String -> [String] -> (Maybe String) -> IO (String, Bool)
#ifndef mingw32_HOST_OS
+{- This implementation interleves stdout and stderr in exactly the order
+ - the process writes them. -}
processTranscript cmd opts input = do
(readf, writef) <- createPipe
readh <- fdToHandle readf
@@ -173,10 +177,7 @@ processTranscript cmd opts input = do
}
hClose writeh
- -- fork off a thread to start consuming the output
- transcript <- hGetContents readh
- outMVar <- newEmptyMVar
- _ <- forkIO $ E.evaluate (length transcript) >> putMVar outMVar ()
+ get <- mkreader readh
-- now write and flush any input
case input of
@@ -188,15 +189,46 @@ processTranscript cmd opts input = do
hClose inh
Nothing -> return ()
- -- wait on the output
- takeMVar outMVar
- hClose readh
+ transcript <- get
ok <- checkSuccessProcess pid
return (transcript, ok)
#else
-processTranscript = error "processTranscript TODO"
+{- This implementation for Windows puts stderr after stdout. -}
+processTranscript cmd opts input = do
+ p@(_, _, _, pid) <- createProcess $
+ (proc cmd opts)
+ { std_in = if isJust input then CreatePipe else Inherit
+ , std_out = CreatePipe
+ , std_err = CreatePipe
+ }
+
+ getout <- mkreader (stdoutHandle p)
+ geterr <- mkreader (stderrHandle p)
+
+ case input of
+ Just s -> do
+ let inh = stdinHandle p
+ unless (null s) $ do
+ hPutStr inh s
+ hFlush inh
+ hClose inh
+ Nothing -> return ()
+
+ transcript <- (++) <$> getout <*> geterr
+ ok <- checkSuccessProcess pid
+ return (transcript, ok)
#endif
+ where
+ mkreader h = do
+ s <- hGetContents h
+ v <- newEmptyMVar
+ void $ forkIO $ do
+ void $ E.evaluate (length s)
+ putMVar v ()
+ return $ do
+ takeMVar v
+ return s
{- Runs a CreateProcessRunner, on a CreateProcess structure, that
- is adjusted to pipe only from/to a single StdHandle, and passes