Skip to content

Exception handling by example

Yuras edited this page Nov 15, 2014 · 1 revision

Here I'll collect useful or simply interesting examples of exception handling in Haskell. It is not directly related to io-region package.

Mutual throwTo (example: timeout)

Here is possible implementation of timeout (from ghc sources):

newtype Timeout = Timeout Unique
instance Show Timeout where

timeout :: Int -> IO a -> IO a
timeout n f = do
  pid <- myThreadId
  ex <- fmap Timeout newUnique
  handleJust (\e -> if e == ex then Just () else Nothing)
             (\_ -> return Nothing)
             (bracket (forkIOWithUnmask $ \unmask ->
                           unmask $ threadDelay n >> throwTo pid ex)
                      (uninterruptibleMask_ . killThread)
                      (\_ -> fmap Just f))

Note that killThread is implemented via throwTo, so we have mutual throwTo.

throwTo is interruptible and atomic, so only one throwTo will succeed interrupting another one.

uninterruptibleMask_ here looks unnecessary in the first glance because killThread can't block here (but can be descheduled.) But:

  • killThread is interruptible even when it doesn't block, unlike most other actions
  • it can actually block here waiting for child thread to unmask async exceptions But uninterruptibleMask_ here is guaranteed to take small (well, bounded) amount of time, so it is safe.