typed-process 0.2.5.0 → 0.2.6.0
raw patch · 4 files changed
+56/−38 lines, 4 filesdep +unliftio-corePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: unliftio-core
API changes (from Hackage documentation)
- System.Process.Typed: withProcess :: ProcessConfig stdin stdout stderr -> (Process stdin stdout stderr -> IO a) -> IO a
+ System.Process.Typed: withProcess :: MonadUnliftIO m => ProcessConfig stdin stdout stderr -> (Process stdin stdout stderr -> m a) -> m a
- System.Process.Typed: withProcessTerm :: ProcessConfig stdin stdout stderr -> (Process stdin stdout stderr -> IO a) -> IO a
+ System.Process.Typed: withProcessTerm :: MonadUnliftIO m => ProcessConfig stdin stdout stderr -> (Process stdin stdout stderr -> m a) -> m a
- System.Process.Typed: withProcessTerm_ :: ProcessConfig stdin stdout stderr -> (Process stdin stdout stderr -> IO a) -> IO a
+ System.Process.Typed: withProcessTerm_ :: MonadUnliftIO m => ProcessConfig stdin stdout stderr -> (Process stdin stdout stderr -> m a) -> m a
- System.Process.Typed: withProcessWait :: ProcessConfig stdin stdout stderr -> (Process stdin stdout stderr -> IO a) -> IO a
+ System.Process.Typed: withProcessWait :: MonadUnliftIO m => ProcessConfig stdin stdout stderr -> (Process stdin stdout stderr -> m a) -> m a
- System.Process.Typed: withProcessWait_ :: ProcessConfig stdin stdout stderr -> (Process stdin stdout stderr -> IO a) -> IO a
+ System.Process.Typed: withProcessWait_ :: MonadUnliftIO m => ProcessConfig stdin stdout stderr -> (Process stdin stdout stderr -> m a) -> m a
- System.Process.Typed: withProcess_ :: ProcessConfig stdin stdout stderr -> (Process stdin stdout stderr -> IO a) -> IO a
+ System.Process.Typed: withProcess_ :: MonadUnliftIO m => ProcessConfig stdin stdout stderr -> (Process stdin stdout stderr -> m a) -> m a
Files
- ChangeLog.md +5/−0
- src/System/Process/Typed.hs +41/−31
- test/System/Process/TypedSpec.hs +5/−5
- typed-process.cabal +5/−2
ChangeLog.md view
@@ -1,5 +1,10 @@ # ChangeLog for typed-process +## Unreleased++* The cleanup thread applies an `unmask` to the actions which wait for a+ process to exit, allowing the action to be interruptible.+ ## 0.2.5.0 * Add a `nullStream` [#24](https://github.com/fpco/typed-process/pull/24)
src/System/Process/Typed.hs view
@@ -97,7 +97,8 @@ import qualified Data.ByteString as S import Data.ByteString.Lazy.Internal (defaultChunkSize)-import Control.Exception (assert, evaluate, throwIO, Exception, SomeException, finally, bracket, onException, catch, try)+import qualified Control.Exception as E+import Control.Exception hiding (bracket, finally) import Control.Monad (void) import Control.Monad.IO.Class import qualified System.Process as P@@ -105,7 +106,7 @@ import System.IO (Handle, hClose, IOMode(ReadWriteMode), withBinaryFile) import System.IO.Error (isPermissionError) import Control.Concurrent (threadDelay)-import Control.Concurrent.Async (async, cancel, waitCatch)+import Control.Concurrent.Async (async, asyncWithUnmask, cancel, waitCatch) import Control.Concurrent.STM (newEmptyTMVarIO, atomically, putTMVar, TMVar, readTMVar, tryReadTMVar, STM, tryPutTMVar, throwSTM, catchSTM) import System.Exit (ExitCode (ExitSuccess)) import System.Process.Typed.Internal@@ -113,6 +114,7 @@ import qualified Data.ByteString.Lazy.Char8 as L8 import Data.String (IsString (fromString)) import GHC.RTS.Flags (getConcFlags, ctxtSwitchTime)+import Control.Monad.IO.Unlift #if MIN_VERSION_process(1, 4, 0) && !WINDOWS import System.Posix.Types (GroupID, UserID)@@ -667,8 +669,8 @@ <*> ssCreate pcStderr pConfig merrH pExitCode <- newEmptyTMVarIO- waitingThread <- async $ do- ec <-+ waitingThread <- asyncWithUnmask $ \unmask -> do+ ec <- unmask $ -- make sure the masking state from a bracket isn't inherited if multiThreadedRuntime then P.waitForProcess pHandle else do@@ -759,10 +761,10 @@ -- <https://github.com/fpco/typed-process/issues/25>. -- -- @since 0.2.5.0-withProcessTerm- :: ProcessConfig stdin stdout stderr- -> (Process stdin stdout stderr -> IO a)- -> IO a+withProcessTerm :: (MonadUnliftIO m)+ => ProcessConfig stdin stdout stderr+ -> (Process stdin stdout stderr -> m a)+ -> m a withProcessTerm config = bracket (startProcess config) stopProcess -- | Uses the bracket pattern to call 'startProcess'. Unlike@@ -771,10 +773,10 @@ -- inner function throws an exception. -- -- @since 0.2.5.0-withProcessWait- :: ProcessConfig stdin stdout stderr- -> (Process stdin stdout stderr -> IO a)- -> IO a+withProcessWait :: (MonadUnliftIO m)+ => ProcessConfig stdin stdout stderr+ -> (Process stdin stdout stderr -> m a)+ -> m a withProcessWait config f = bracket (startProcess config)@@ -784,19 +786,20 @@ -- | Deprecated synonym for 'withProcessTerm'. -- -- @since 0.1.0.0-withProcess :: ProcessConfig stdin stdout stderr- -> (Process stdin stdout stderr -> IO a)- -> IO a+withProcess :: (MonadUnliftIO m)+ => ProcessConfig stdin stdout stderr+ -> (Process stdin stdout stderr -> m a)+ -> m a withProcess = withProcessTerm {-# DEPRECATED withProcess "Please consider using withProcessWait, or instead use withProcessTerm" #-} -- | Same as 'withProcessTerm', but also calls 'checkExitCode' -- -- @since 0.2.5.0-withProcessTerm_- :: ProcessConfig stdin stdout stderr- -> (Process stdin stdout stderr -> IO a)- -> IO a+withProcessTerm_ :: (MonadUnliftIO m)+ => ProcessConfig stdin stdout stderr+ -> (Process stdin stdout stderr -> m a)+ -> m a withProcessTerm_ config = bracket (startProcess config) (\p -> stopProcess p `finally` checkExitCode p)@@ -804,10 +807,10 @@ -- | Same as 'withProcessWait', but also calls 'checkExitCode' -- -- @since 0.2.5.0-withProcessWait_- :: ProcessConfig stdin stdout stderr- -> (Process stdin stdout stderr -> IO a)- -> IO a+withProcessWait_ :: (MonadUnliftIO m)+ => ProcessConfig stdin stdout stderr+ -> (Process stdin stdout stderr -> m a)+ -> m a withProcessWait_ config f = bracket (startProcess config) stopProcess@@ -816,9 +819,10 @@ -- | Deprecated synonym for 'withProcessTerm_'. -- -- @since 0.1.0.0-withProcess_ :: ProcessConfig stdin stdout stderr- -> (Process stdin stdout stderr -> IO a)- -> IO a+withProcess_ :: (MonadUnliftIO m)+ => ProcessConfig stdin stdout stderr+ -> (Process stdin stdout stderr -> m a)+ -> m a withProcess_ = withProcessTerm_ {-# DEPRECATED withProcess_ "Please consider using withProcessWait_, or instead use withProcessTerm_" #-} @@ -933,10 +937,10 @@ where pc' = setStderr byteStringOutput pc -withProcessInterleave- :: ProcessConfig stdin stdoutIgnored stderrIgnored- -> (Process stdin (STM L.ByteString) () -> IO a)- -> IO a+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 bracket P.createPipe (\(r, w) -> hClose r >> hClose w) $ \(readEnd, writeEnd) -> do@@ -949,7 +953,7 @@ withProcess pc' $ \p -> do -- Now that the process is forked, close the writer end of this -- pipe, otherwise the reader end will never give an EOF.- hClose writeEnd+ liftIO $ hClose writeEnd inner p -- | Same as 'readProcess', but interleaves stderr with stdout.@@ -1142,3 +1146,9 @@ -- @since 0.1.1 unsafeProcessHandle :: Process stdin stdout stderr -> P.ProcessHandle unsafeProcessHandle = pHandle++bracket :: MonadUnliftIO m => IO a -> (a -> IO b) -> (a -> m c) -> m c+bracket before after thing = withRunInIO $ \run -> E.bracket before after (run . thing)++finally :: MonadUnliftIO m => m a -> IO () -> m a+finally thing after = withRunInIO $ \run -> E.finally (run thing) after
test/System/Process/TypedSpec.hs view
@@ -112,14 +112,14 @@ raw <- S.readFile fp encoded `shouldBe` B64.encode raw - describe "withProcessWait" $ do+ describe "withProcessWait" $ it "succeeds with sleep" $ do p <- withProcessWait (proc "sleep" ["1"]) pure- checkExitCode p+ checkExitCode p :: IO () - describe "withProcessWait_" $ do- it "succeeds with sleep" $ do- withProcessWait_ (proc "sleep" ["1"]) $ const $ pure ()+ describe "withProcessWait_" $+ it "succeeds with sleep"+ ((withProcessWait_ (proc "sleep" ["1"]) $ const $ pure ()) :: IO ()) -- These tests fail on older GHCs/process package versions -- because, apparently, waitForProcess isn't interruptible. See
typed-process.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: ad27eee8ecda9f23b7e99ea05885ad76c916b5210115a132a56a28c79437d01c+-- hash: f8fdbd0397d67fa0c8d6c96e3e95d3d6eb56d94fc13f0350fc60ff855d44d671 name: typed-process-version: 0.2.5.0+version: 0.2.6.0 synopsis: Run external processes, with strong typing of streams description: Please see the tutorial at <https://haskell-lang.org/library/typed-process> category: System@@ -41,6 +41,7 @@ , process >=1.2 , stm , transformers+ , unliftio-core if os(windows) cpp-options: -DWINDOWS default-language: Haskell2010@@ -65,6 +66,7 @@ , temporary , transformers , typed-process+ , unliftio-core default-language: Haskell2010 test-suite typed-process-test-single-threaded@@ -86,4 +88,5 @@ , temporary , transformers , typed-process+ , unliftio-core default-language: Haskell2010