
#10298: Infinite loop when shared libraries are unavailable -------------------------------------+------------------------------------- Reporter: snoyberg | Owner: simonmar Type: bug | Status: new Priority: normal | Milestone: Component: Runtime System | Version: 7.10.1 Resolution: | Keywords: Operating System: Linux | Architecture: x86_64 Type of failure: Runtime crash | (amd64) Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by rwbarton): Actually there are more hidden traps. The `IOError` that is raised from the failure of `iconv_open` is produced by `errnoToIOError`, which is defined as {{{ errnoToIOError loc errno maybeHdl maybeName = unsafePerformIO $ do str <- strerror errno >>= peekCString return (IOError maybeHdl errType loc str (Just errno') maybeName) where -- ... }}} This means that matching on the `IOError` constructor will recursively raise another exception, since `peekCString` uses the user's locale. In `GHC.TopHandler`, `real_handler` matches on the `IOError` constructor to decide how to exit. So a possible fix is {{{ diff --git a/libraries/base/GHC/TopHandler.hs b/libraries/base/GHC/TopHandler.hs index d7c0038..5d4094a 100644 --- a/libraries/base/GHC/TopHandler.hs +++ b/libraries/base/GHC/TopHandler.hs @@ -157,14 +157,25 @@ real_handler exit se = do Just (ExitFailure n) -> exit n -- EPIPE errors received for stdout are ignored (#2699) - _ -> case fromException se of + _ -> catch (case fromException se of Just IOError{ ioe_type = ResourceVanished, ioe_errno = Just ioe, ioe_handle = Just hdl } | Errno ioe == ePIPE, hdl == stdout -> exit 0 _ -> do reportError se exit 1 - + ) (disasterHandler exit) + +-- don't use errorBelch() directly, because we cannot call varargs functions +-- using the FFI. +foreign import ccall unsafe "HsBase.h errorBelch2" + errorBelch :: CString -> CString -> IO () + +disasterHandler :: (Int -> IO a) -> IOError -> IO a +disasterHandler exit _ = + withCAString "%s" $ \fmt -> + withCAString "encountered an exception while trying to report an exception" $ \msg -> + errorBelch fmt msg >> exit 1 -- try to flush stdout/stderr, but don't worry if we fail -- (these handles might have errors, and we don't want to go into }}} though it feels a bit artificial. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10298#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler