dev: ignore SIGPIPE errors from truncated output in a more robust way [#2405]
This commit is contained in:
parent
c335f93bcb
commit
0750a27d00
@ -149,7 +149,7 @@ import System.Console.ANSI (Color(..),ColorIntensity(..), ConsoleLayer
|
|||||||
import System.Console.Terminal.Size (Window (Window), size)
|
import System.Console.Terminal.Size (Window (Window), size)
|
||||||
import System.Directory (getHomeDirectory, getModificationTime, findExecutable)
|
import System.Directory (getHomeDirectory, getModificationTime, findExecutable)
|
||||||
import System.Environment (getArgs, lookupEnv, setEnv, getProgName)
|
import System.Environment (getArgs, lookupEnv, setEnv, getProgName)
|
||||||
import System.Exit (exitFailure, exitSuccess)
|
import System.Exit (exitFailure)
|
||||||
import System.FilePath (isRelative, (</>))
|
import System.FilePath (isRelative, (</>))
|
||||||
import "Glob" System.FilePath.Glob (glob)
|
import "Glob" System.FilePath.Glob (glob)
|
||||||
import System.Info (os)
|
import System.Info (os)
|
||||||
@ -287,31 +287,32 @@ exitWithErrorMessage msg = printError msg >> exitFailure
|
|||||||
-- it adds (english) text explaining the problem and what to do.
|
-- it adds (english) text explaining the problem and what to do.
|
||||||
--
|
--
|
||||||
-- Some exceptions this does not handle:
|
-- Some exceptions this does not handle:
|
||||||
-- ExitCode (exitSuccess / exitFailure / exitWith calls)
|
-- ExitCode (exitSuccess/exitFailure/exitWith),
|
||||||
-- and UserInterrupt (control-C).
|
-- UserInterrupt (control-C).
|
||||||
|
--
|
||||||
|
-- Also, this ignores SIGPIPE errors, which are usually harmless,
|
||||||
|
-- caused when our output is truncated in a piped command.
|
||||||
--
|
--
|
||||||
exitOnError :: IO () -> IO ()
|
exitOnError :: IO () -> IO ()
|
||||||
exitOnError = flip catches
|
exitOnError = flip catches [
|
||||||
[
|
|
||||||
-- Handler (\(e::SomeException) -> error' $ pshow e), -- debug
|
-- Handler (\(e::SomeException) -> error' $ pshow e), -- debug
|
||||||
Handler (\(e::UnicodeException) -> exitUnicode e)
|
Handler (\(e::UnicodeException) -> exitUnicode e)
|
||||||
,Handler (\(e::IOException) -> if
|
,Handler (\(e::IOException) -> if
|
||||||
| isUnicodeError e -> exitUnicode e
|
| isUnicodeError e -> exitUnicode e
|
||||||
| isBrokenPipeError e -> exitSuccess
|
|
||||||
| otherwise -> exitOther e)
|
| otherwise -> exitOther e)
|
||||||
,Handler (\(e::ErrorCall) -> exitOther e)
|
,Handler (\(e::ErrorCall) -> exitOther e)
|
||||||
]
|
] . ignoreSigPipe
|
||||||
|
|
||||||
where
|
where
|
||||||
-- After adding the above handler, truncating program output eg by piping into head
|
-- | Ignore SIGPIPE errors.
|
||||||
-- showed "hledger: Error: <stdout>: commitBuffer: resource vanished ( Broken pipe )".
|
-- This is copied from System.Process.Internals in process 1.6.20.0+,
|
||||||
-- As far as I know, this is an IOException and the best we can do is check for that wording
|
-- since that version of process comes only with ghc 9.10.2+.
|
||||||
-- and treat those as non-errors. (Will this mask any real errors ? XXX)
|
ignoreSigPipe :: IO () -> IO ()
|
||||||
isBrokenPipeError :: Exception e => e -> Bool
|
ignoreSigPipe = handle $ \e -> case e of
|
||||||
isBrokenPipeError ex =
|
IOError { ioe_type = ResourceVanished
|
||||||
let msg = map toLower (show ex) in any (`isInfixOf` msg) [
|
, ioe_errno = Just ioe }
|
||||||
"broken pipe"
|
| Errno ioe == ePIPE -> return ()
|
||||||
]
|
_ -> throwIO e
|
||||||
|
|
||||||
-- Many decoding failures do not produce a UnicodeException, unfortunately.
|
-- Many decoding failures do not produce a UnicodeException, unfortunately.
|
||||||
-- So this fragile hack detects them from the error message.
|
-- So this fragile hack detects them from the error message.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user