This is a cookbook for the usage of safe-exceptions
. You should
start off by
reading the README,
or at least
the quickstart section.
Request to readers: if there are specific workflows that you're unsure of how to accomplish with this library, please ask so we can add them here. Issues and pull requests very much welcome!
In order to define an async exception, you must leverage the
extensible exception machinery, as demonstrated below. Try running the
program, and then comment out the implementation of toException
and
fromException
to see the difference in behavior.
#!/usr/bin/env stack
-- stack --resolver lts-6.4 runghc --package safe-exceptions-0.1.0.0
import Control.Concurrent (forkIO, newEmptyMVar, putMVar, takeMVar,
threadDelay)
import Control.Exception.Safe
import Data.Typeable (Typeable, cast)
data MyAsyncException = MyAsyncException
deriving (Show, Typeable)
instance Exception MyAsyncException where
toException = toException . SomeAsyncException
fromException se = do
SomeAsyncException e <- fromException se
cast e
main :: IO ()
main = do
baton <- newEmptyMVar -- give the handler a chance to run
tid <- forkIO $ threadDelay maxBound
`withException`
(\e -> print ("Inside withException", e :: MyAsyncException))
`finally` putMVar baton ()
throwTo tid MyAsyncException
takeMVar baton
putStrLn "Done!"
The reason the Inside withException
message isn't printed without
the implementation of toException
and fromException
given above is
that throwTo
wraps MyAsyncException
inside a different async
exception type, which foils the exception handler from firing.
NOTE: The above code is not recommended concurrency code. If you have to do something like this, please use the async package.