typed-process 0.2.11.0 → 0.2.11.1
raw patch · 4 files changed
+96/−84 lines, 4 filesdep ~hspec
Dependency ranges changed: hspec
Files
- ChangeLog.md +5/−1
- src/System/Process/Typed.hs +47/−44
- src/System/Process/Typed/Internal.hs +37/−36
- typed-process.cabal +7/−3
ChangeLog.md view
@@ -1,8 +1,12 @@ # ChangeLog for typed-process +## 0.2.11.1++* No user-visible changes+ ## 0.2.11.0 -* Expose `System.Process.Typed.Internal`+* Expose more from `System.Process.Typed.Internal` ## 0.2.10.0
src/System/Process/Typed.hs view
@@ -178,7 +178,7 @@ -- @since 0.1.0.0 startProcess :: MonadIO m => ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> m (Process stdin stdout stderr) startProcess pConfig'@ProcessConfig {..} = liftIO $ do ssStream pcStdin $ \realStdin ->@@ -256,25 +256,8 @@ -- Process didn't exit yet, let's terminate it and -- then call waitForProcess ourselves Left _ -> do- eres <- try $ P.terminateProcess pHandle- ec <-- case eres of- Left e- -- On Windows, with the single-threaded runtime, it- -- seems that if a process has already exited, the- -- call to terminateProcess will fail with a- -- permission denied error. To work around this, we- -- catch this exception and then immediately- -- waitForProcess. There's a chance that there may be- -- other reasons for this permission error to appear,- -- in which case this code may allow us to wait too- -- long for a child process instead of erroring out.- -- Recommendation: always use the multi-threaded- -- runtime!- | isPermissionError e && not multiThreadedRuntime && isWindows ->- P.waitForProcess pHandle- | otherwise -> throwIO e- Right () -> P.waitForProcess pHandle+ terminateProcess pHandle+ ec <- P.waitForProcess pHandle success <- atomically $ tryPutTMVar pExitCode ec evaluate $ assert success () @@ -282,6 +265,26 @@ where pConfig = clearStreams pConfig' + terminateProcess pHandle = do+ eres <- try $ P.terminateProcess pHandle+ case eres of+ Left e+ -- On Windows, with the single-threaded runtime, it+ -- seems that if a process has already exited, the+ -- call to terminateProcess will fail with a+ -- permission denied error. To work around this, we+ -- catch this exception and then immediately+ -- waitForProcess. There's a chance that there may be+ -- other reasons for this permission error to appear,+ -- in which case this code may allow us to wait too+ -- long for a child process instead of erroring out.+ -- Recommendation: always use the multi-threaded+ -- runtime!+ | isPermissionError e && not multiThreadedRuntime && isWindows ->+ pure ()+ | otherwise -> throwIO e+ Right () -> pure ()+ foreign import ccall unsafe "rtsSupportsBoundThreads" multiThreadedRuntime :: Bool @@ -314,9 +317,9 @@ -- @since 0.2.5.0 withProcessTerm :: (MonadUnliftIO m) => ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> (Process stdin stdout stderr -> m a)- -- ^+ -- ^ -> m a withProcessTerm config = bracket (startProcess config) stopProcess @@ -331,9 +334,9 @@ -- @since 0.2.5.0 withProcessWait :: (MonadUnliftIO m) => ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> (Process stdin stdout stderr -> m a)- -- ^+ -- ^ -> m a withProcessWait config f = bracket@@ -349,7 +352,7 @@ -> (Process stdin stdout stderr -> m a) -> m a withProcess = withProcessTerm-{-# DEPRECATED withProcess "Please consider using withProcessWait, or instead use withProcessTerm" #-}+{-# DEPRECATED withProcess "Please consider using `withProcessWait`, or instead use `withProcessTerm`" #-} -- | Same as 'withProcessTerm', but also calls 'checkExitCode' --@@ -359,9 +362,9 @@ -- @since 0.2.5.0 withProcessTerm_ :: (MonadUnliftIO m) => ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> (Process stdin stdout stderr -> m a)- -- ^+ -- ^ -> m a withProcessTerm_ config = bracket (startProcess config)@@ -372,9 +375,9 @@ -- @since 0.2.5.0 withProcessWait_ :: (MonadUnliftIO m) => ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> (Process stdin stdout stderr -> m a)- -- ^+ -- ^ -> m a withProcessWait_ config f = bracket (startProcess config)@@ -389,7 +392,7 @@ -> (Process stdin stdout stderr -> m a) -> m a withProcess_ = withProcessTerm_-{-# DEPRECATED withProcess_ "Please consider using withProcessWait_, or instead use withProcessTerm_" #-}+{-# DEPRECATED withProcess_ "Please consider using `withProcessWait_`, or instead use `withProcessTerm_`" #-} -- | Run a process, capture its standard output and error as a -- 'L.ByteString', wait for it to complete, and then return its exit@@ -401,7 +404,7 @@ -- @since 0.1.0.0 readProcess :: MonadIO m => ProcessConfig stdin stdoutIgnored stderrIgnored- -- ^+ -- ^ -> m (ExitCode, L.ByteString, L.ByteString) readProcess pc = liftIO $ withProcess pc' $ \p -> atomically $ (,,)@@ -420,7 +423,7 @@ -- @since 0.1.0.0 readProcess_ :: MonadIO m => ProcessConfig stdin stdoutIgnored stderrIgnored- -- ^+ -- ^ -> m (L.ByteString, L.ByteString) readProcess_ pc = liftIO $ withProcess pc' $ \p -> atomically $ do@@ -441,7 +444,7 @@ readProcessStdout :: MonadIO m => ProcessConfig stdin stdoutIgnored stderr- -- ^+ -- ^ -> m (ExitCode, L.ByteString) readProcessStdout pc = liftIO $ withProcess pc' $ \p -> atomically $ (,)@@ -459,7 +462,7 @@ readProcessStdout_ :: MonadIO m => ProcessConfig stdin stdoutIgnored stderr- -- ^+ -- ^ -> m L.ByteString readProcessStdout_ pc = liftIO $ withProcess pc' $ \p -> atomically $ do@@ -478,7 +481,7 @@ readProcessStderr :: MonadIO m => ProcessConfig stdin stdout stderrIgnored- -- ^+ -- ^ -> m (ExitCode, L.ByteString) readProcessStderr pc = liftIO $ withProcess pc' $ \p -> atomically $ (,)@@ -496,7 +499,7 @@ readProcessStderr_ :: MonadIO m => ProcessConfig stdin stdout stderrIgnored- -- ^+ -- ^ -> m L.ByteString readProcessStderr_ pc = liftIO $ withProcess pc' $ \p -> atomically $ do@@ -510,9 +513,9 @@ withProcessInterleave :: (MonadUnliftIO m) => ProcessConfig stdin stdoutIgnored stderrIgnored- -- ^+ -- ^ -> (Process stdin (STM L.ByteString) () -> m a)- -- ^+ -- ^ -> m a withProcessInterleave pc inner = -- Create a pipe to be shared for both stdout and stderr@@ -538,7 +541,7 @@ readProcessInterleaved :: MonadIO m => ProcessConfig stdin stdoutIgnored stderrIgnored- -- ^+ -- ^ -> m (ExitCode, L.ByteString) readProcessInterleaved pc = liftIO $@@ -556,9 +559,9 @@ readProcessInterleaved_ :: MonadIO m => ProcessConfig stdin stdoutIgnored stderrIgnored- -- ^+ -- ^ -> m L.ByteString- -- ^+ -- ^ readProcessInterleaved_ pc = liftIO $ withProcessInterleave pc $ \p -> atomically $ do@@ -574,9 +577,9 @@ -- @since 0.1.0.0 runProcess :: MonadIO m => ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> m ExitCode- -- ^+ -- ^ runProcess pc = liftIO $ withProcess pc waitExitCode -- | Same as 'runProcess', but instead of returning the@@ -585,7 +588,7 @@ -- @since 0.1.0.0 runProcess_ :: MonadIO m => ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> m () runProcess_ pc = liftIO $ withProcess pc checkExitCode
src/System/Process/Typed/Internal.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE DataKinds #-}@@ -223,9 +224,9 @@ -- -- @since 0.1.0.0 setStdin :: StreamSpec 'STInput stdin- -- ^+ -- ^ -> ProcessConfig stdin0 stdout stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setStdin spec pc = pc { pcStdin = spec } @@ -235,9 +236,9 @@ -- -- @since 0.1.0.0 setStdout :: StreamSpec 'STOutput stdout- -- ^+ -- ^ -> ProcessConfig stdin stdout0 stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setStdout spec pc = pc { pcStdout = spec } @@ -247,9 +248,9 @@ -- -- @since 0.1.0.0 setStderr :: StreamSpec 'STOutput stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr0- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setStderr spec pc = pc { pcStderr = spec } @@ -259,9 +260,9 @@ -- -- @since 0.1.0.0 setWorkingDir :: FilePath- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setWorkingDir dir pc = pc { pcWorkingDir = Just dir } @@ -270,7 +271,7 @@ -- @since 0.2.2.0 setWorkingDirInherit :: ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setWorkingDirInherit pc = pc { pcWorkingDir = Nothing } @@ -280,9 +281,9 @@ -- -- @since 0.1.0.0 setEnv :: [(String, String)]- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setEnv env pc = pc { pcEnv = Just env } @@ -291,7 +292,7 @@ -- @since 0.2.2.0 setEnvInherit :: ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setEnvInherit pc = pc { pcEnv = Nothing } @@ -303,9 +304,9 @@ -- @since 0.1.0.0 setCloseFds :: Bool- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setCloseFds x pc = pc { pcCloseFds = x } @@ -316,9 +317,9 @@ -- @since 0.1.0.0 setCreateGroup :: Bool- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setCreateGroup x pc = pc { pcCreateGroup = x } @@ -330,9 +331,9 @@ -- @since 0.1.0.0 setDelegateCtlc :: Bool- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setDelegateCtlc x pc = pc { pcDelegateCtlc = x } @@ -345,9 +346,9 @@ -- @since 0.1.0.0 setDetachConsole :: Bool- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setDetachConsole x pc = pc { pcDetachConsole = x } @@ -358,9 +359,9 @@ -- @since 0.1.0.0 setCreateNewConsole :: Bool- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setCreateNewConsole x pc = pc { pcCreateNewConsole = x } @@ -372,9 +373,9 @@ -- @since 0.1.0.0 setNewSession :: Bool- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setNewSession x pc = pc { pcNewSession = x } #endif@@ -388,9 +389,9 @@ -- @since 0.1.0.0 setChildGroup :: GroupID- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setChildGroup x pc = pc { pcChildGroup = Just x } @@ -399,7 +400,7 @@ -- @since 0.2.2.0 setChildGroupInherit :: ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setChildGroupInherit pc = pc { pcChildGroup = Nothing } @@ -411,9 +412,9 @@ -- @since 0.1.0.0 setChildUser :: UserID- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setChildUser x pc = pc { pcChildUser = Just x } @@ -422,7 +423,7 @@ -- @since 0.2.2.0 setChildUserInherit :: ProcessConfig stdin stdout stderr- -- ^+ -- ^ -> ProcessConfig stdin stdout stderr setChildUserInherit pc = pc { pcChildUser = Nothing } #endif@@ -443,9 +444,9 @@ -- -- @since 0.1.0.0 mkStreamSpec :: P.StdStream- -- ^+ -- ^ -> (ProcessConfig () () () -> Maybe Handle -> IO (a, IO ()))- -- ^+ -- ^ -> StreamSpec streamType a mkStreamSpec ss f = mkManagedStreamSpec ($ ss) f @@ -460,9 +461,9 @@ -- -- @since 0.2.10.0 mkPipeStreamSpec :: (ProcessConfig () () () -> Handle -> IO (a, IO ()))- -- ^+ -- ^ -> StreamSpec streamType a- -- ^+ -- ^ mkPipeStreamSpec f = mkStreamSpec P.CreatePipe $ \pc mh -> case mh of Just h -> f pc h@@ -472,9 +473,9 @@ -- 'P.StdStream' and a helper function. This function is the same as -- the helper in 'mkStreamSpec' mkManagedStreamSpec :: (forall b. (P.StdStream -> IO b) -> IO b)- -- ^+ -- ^ -> (ProcessConfig () () () -> Maybe Handle -> IO (a, IO ()))- -- ^+ -- ^ -> StreamSpec streamType a mkManagedStreamSpec ss f = StreamSpec ss (\pc mh -> Cleanup (f pc mh))
typed-process.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack name: typed-process-version: 0.2.11.0+version: 0.2.11.1 synopsis: Run external processes, with strong typing of streams description: Please see the tutorial at <https://github.com/fpco/typed-process#readme> category: System@@ -53,12 +53,14 @@ hs-source-dirs: test ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-tool-depends:+ hspec-discover:hspec-discover build-depends: async >=2.0 , base >=4.12 && <5 , base64-bytestring , bytestring- , hspec+ , hspec ==2.* , process >=1.2 , stm , temporary@@ -75,12 +77,14 @@ Paths_typed_process hs-source-dirs: test+ build-tool-depends:+ hspec-discover:hspec-discover build-depends: async >=2.0 , base >=4.12 && <5 , base64-bytestring , bytestring- , hspec+ , hspec ==2.* , process >=1.2 , stm , temporary