Dangers of registerTimeout (was: Race-condition in alternative 'System.Timeout.timeout' implementation)

Herbert Valerio Riedel hvr at gnu.org
Tue Feb 26 10:04:06 CET 2013


Herbert Valerio Riedel <hvr at gnu.org> writes:

[...]

>                    (bracket (E.registerTimeout em to (throwTo tid ex))
>                             (E.unregisterTimeout em)
>                             (\_ -> fmap Just f))

...after some discussion on #ghc, I've realized, that 'registerTimeout'
is dangerous if used improperly; it should be avoided to call any
blocking operation (or throw exceptions) in the timeout-handler, as
otherwise the I/O manager loop stops processing new events (at least
with GHC-7.6.2) until the timeout-action completes; the following code
demonstrates this issue by triggering a neverending timeout-action which
effectively makes the Haskell process non-responsive.

--8<---------------cut here---------------start------------->8---
import           Control.Concurrent
import qualified GHC.Event as E

messupEventManager :: IO ()
messupEventManager = do
    mv <- newMVar ()
    Just em <- E.getSystemEventManager
    E.registerTimeout em 5000000 (putStrLn "...blocking NOW!" >> putMVar mv ())
    putStrLn "...in about 5 seconds the I/O manager will get stuck..."
--8<---------------cut here---------------end--------------->8---

So maybe a warning in the documentation of registerTimeout may be
appropriate telling users of registerTimeout that care should be taken
to avoid operations blocking for non-negligible time (or throwing
exceptions) in the timeout-handler, as otherwise in the best case the
I/O processing latency suffers and in the worst case the I/O manager may
come to a halt altogether.

cheers,
  hvr



More information about the Glasgow-haskell-users mailing list