Skip to content

Commit

Permalink
Add ExitCodeException smart constructors
Browse files Browse the repository at this point in the history
`ExitCodeException`s thrown by `typed-process` never populate the
`eceStdout` or `eceStderr` fields, and it's impossible to construct an
`ExitCodeException` manually because the `pConfig` field accessor is not
public. This patch adds two smart constructors,
`exitCodeExceptionWithOutput` and `exitCodeExceptionNoOutput`, to fill
these use cases.
  • Loading branch information
9999years committed Aug 15, 2024
1 parent d5e9fb3 commit b58f1cb
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 10 deletions.
51 changes: 45 additions & 6 deletions src/System/Process/Typed.hs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ module System.Process.Typed

-- * Exceptions
, ExitCodeException (..)
, exitCodeExceptionWithOutput
, exitCodeExceptionNoOutput
, ByteStringOutputException (..)

-- * Re-exports
Expand Down Expand Up @@ -634,12 +636,7 @@ checkExitCodeSTM p = do
ec <- readTMVar (pExitCode p)
case ec of
ExitSuccess -> return ()
_ -> throwSTM ExitCodeException
{ eceExitCode = ec
, eceProcessConfig = clearStreams (pConfig p)
, eceStdout = L.empty
, eceStderr = L.empty
}
_ -> throwSTM $ exitCodeExceptionNoOutput p ec

-- | Internal
clearStreams :: ProcessConfig stdin stdout stderr -> ProcessConfig () () ()
Expand Down Expand Up @@ -688,3 +685,45 @@ getStderr = pStderr
-- @since 0.1.1
unsafeProcessHandle :: Process stdin stdout stderr -> P.ProcessHandle
unsafeProcessHandle = pHandle

-- | Get an 'ExitCodeException' containing the process's stdout and stderr data.
--
-- Note that this will call 'waitExitCode' to block until the process exits, if
-- it has not exited already.
--
-- Unlike 'checkExitCode' and similar, this will return an 'ExitCodeException'
-- even if the process exits with 'ExitSuccess'.
--
-- @since 0.2.12.0
exitCodeExceptionWithOutput :: MonadIO m
=> Process stdin (STM L.ByteString) (STM L.ByteString)
-> m ExitCodeException
exitCodeExceptionWithOutput process = liftIO $ atomically $ do
exitCode <- waitExitCodeSTM process
stdout <- getStdout process
stderr <- getStderr process
pure ExitCodeException
{ eceExitCode = exitCode
, eceProcessConfig = pConfig process
, eceStdout = stdout
, eceStderr = stderr
}

-- | Get an 'ExitCodeException' containing no data other than the exit code and
-- process config.
--
-- Unlike 'checkExitCode' and similar, this will return an 'ExitCodeException'
-- even if the process exits with 'ExitSuccess'.
--
-- @since 0.2.12.0
exitCodeExceptionNoOutput :: Process stdin stdout stderr
-> ExitCode
-> ExitCodeException
exitCodeExceptionNoOutput process exitCode =
ExitCodeException
{ eceExitCode = exitCode
, eceProcessConfig = pConfig process
, eceStdout = L.empty
, eceStderr = L.empty
}

10 changes: 6 additions & 4 deletions src/System/Process/Typed/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -590,11 +590,13 @@ useHandleOpen h = mkStreamSpec (P.UseHandle h) $ \_ _ -> return ((), return ())
useHandleClose :: Handle -> StreamSpec anyStreamType ()
useHandleClose h = mkStreamSpec (P.UseHandle h) $ \_ _ -> return ((), hClose h)

-- | Exception thrown by 'checkExitCode' in the event of a non-success
-- exit code. Note that 'checkExitCode' is called by other functions
-- as well, like 'runProcess_' or 'readProcess_'.
-- | Exception thrown by 'System.Process.Typed.checkExitCode' in the event of a
-- non-success exit code. Note that 'System.Process.Typed.checkExitCode' is
-- called by other functions as well, like 'System.Process.Typed.runProcess_'
-- or 'System.Process.Typed.readProcess_'.
--
-- Note that several functions that throw an 'ExitCodeException' intentionally do not populate 'eceStdout' or 'eceStderr'.
-- Note that 'ExitCodeException's thrown by this package intentionally do not
-- populate 'eceStdout' or 'eceStderr'.
-- This prevents unbounded memory usage for large stdout and stderrs.
--
-- @since 0.1.0.0
Expand Down

0 comments on commit b58f1cb

Please sign in to comment.