[GHC] #7653: incorrect handling of StackOverflow exception in the event manager
GHC
cvs-ghc at haskell.org
Sat Feb 2 15:47:41 CET 2013
#7653: incorrect handling of StackOverflow exception in the event manager
--------------------------+-------------------------------------------------
Reporter: nus | Owner:
Type: bug | Status: new
Priority: normal | Component: libraries/base
Version: 7.7 | Keywords:
Os: Linux | Architecture: Unknown/Multiple
Failure: Runtime crash | Blockedby:
Blocking: | Related:
--------------------------+-------------------------------------------------
Comment(by nus):
`libraries\base\GHC\Event\Manager.hs`, the thunk accummulated in `f'`:
{{{
registerTimeout :: EventManager -> Int -> TimeoutCallback -> IO TimeoutKey
registerTimeout mgr us cb = do
!key <- newUnique (emUniqueSource mgr)
if us <= 0 then cb
else do
now <- getMonotonicTime
let expTime = fromIntegral us / 1000000.0 + now
-- We intentionally do not evaluate the modified map to WHNF here.
-- Instead, we leave a thunk inside the IORef and defer its
-- evaluation until mkTimeout in the event loop. This is a
-- workaround for a nasty IORef contention problem that causes the
-- thread-delay benchmark to take 20 seconds instead of 0.2.
atomicModifyIORef (emTimeouts mgr) $ \f ->
let f' = (Q.insert key expTime cb) . f in (f', ())
wakeManager mgr
return $ TK key
}}}
is evaluated in `applyEdits`:
{{{
step :: EventManager -> TimeoutQueue -> IO (Bool, TimeoutQueue)
step mgr at EventManager{..} tq = do
(timeout, q') <- mkTimeout tq
I.poll emBackend timeout (onFdEvent mgr)
state <- readIORef emState
state `seq` return (state == Running, q')
where
-- | Call all expired timer callbacks and return the time to the
-- next timeout.
mkTimeout :: TimeoutQueue -> IO (Timeout, TimeoutQueue)
mkTimeout q = do
now <- getMonotonicTime
applyEdits <- atomicModifyIORef emTimeouts $ \f -> (id, f)
let (expired, q'') = let q' = applyEdits q in q' `seq` Q.atMost now
q'
sequence_ $ map Q.value expired
let timeout = case Q.minView q'' of
Nothing -> Forever
Just (Q.E _ t _, _) ->
-- This value will always be positive since the call
-- to 'atMost' above removed any timeouts <= 'now'
let t' = t - now in t' `seq` Timeout t'
return (timeout, q'')
}}}
The main `loop :: EventManager -> IO ()` in `cleanup :: EventManager -> IO
()` uses:
{{{
closeControl :: Control -> IO ()
closeControl w = do
_ <- c_close . fromIntegral . controlReadFd $ w
_ <- c_close . fromIntegral . controlWriteFd $ w
#if defined(HAVE_EVENTFD)
_ <- c_close . fromIntegral . controlEventFd $ w
#else
_ <- c_close . fromIntegral . wakeupReadFd $ w
_ <- c_close . fromIntegral . wakeupWriteFd $ w
#endif
return ()
}}}
which doesn't clean up the C side of `newControl :: IO Control`.
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/7653#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list