[GHC] #10298: Infinite loop when shared libraries are unavailable

GHC ghc-devs at haskell.org
Sun Apr 19 23:54:49 UTC 2015


#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


More information about the ghc-tickets mailing list