--
-- Maintainer : libraries@haskell.org
-- Stability : experimental
--- Portability : non-portable
+-- Portability : non-portable (extended exceptions)
--
-- This module provides support for raising and catching both built-in
-- and user-defined exceptions.
--
+-- In addition to exceptions thrown by 'IO' operations, exceptions may
+-- be thrown by pure code (imprecise exceptions) or by external events
+-- (asynchronous exceptions), but may only be caught in the 'IO' monad.
+-- For more details, see:
+--
+-- * /A semantics for imprecise exceptions/, by Simon Peyton Jones,
+-- Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson,
+-- in /PLDI'99/.
+--
+-- * /Asynchronous exceptions in Haskell/, by Simon Marlow, Simon Peyton
+-- Jones, Andy Moran and John Reppy, in /PLDI'01/.
+--
-----------------------------------------------------------------------------
module Control.Exception (
bracket, -- :: IO a -> (a -> IO b) -> (a -> IO c) -> IO ()
bracket_, -- :: IO a -> IO b -> IO c -> IO ()
+ bracketOnError,
finally, -- :: IO a -> IO b -> IO a
-- Also note that the "Prelude" also exports a function called
-- 'Prelude.catch' with a similar type to 'Control.Exception.catch',
-- except that the "Prelude" version only catches the IO and user
--- families of exceptions (as required by Haskell 98). We recommend
--- either hiding the "Prelude" version of
--- 'Prelude.catch' when importing
--- "Control.Exception", or importing
--- "Control.Exception" qualified, to avoid name-clashes.
+-- families of exceptions (as required by Haskell 98).
+--
+-- We recommend either hiding the "Prelude" version of 'Prelude.catch'
+-- when importing "Control.Exception":
+--
+-- > import Prelude hiding (catch)
+--
+-- or importing "Control.Exception" qualified, to avoid name-clashes:
+--
+-- > import qualified Control.Exception as C
+--
+-- and then using @C.catch@
+--
catch :: IO a -- ^ The computation to run
-> (Exception -> IO a) -- ^ Handler to invoke if an exception is raised
bracket_ :: IO a -> IO b -> IO c -> IO c
bracket_ before after thing = bracket before (const after) (const thing)
+-- | Like bracket, but only performs the final action if there was an
+-- exception raised by the in-between computation.
+bracketOnError
+ :: IO a -- ^ computation to run first (\"acquire resource\")
+ -> (a -> IO b) -- ^ computation to run last (\"release resource\")
+ -> (a -> IO c) -- ^ computation to run in-between
+ -> IO c -- returns the value from the in-between computation
+bracketOnError before after thing =
+ block (do
+ a <- before
+ catch
+ (unblock (thing a))
+ (\e -> do { after a; throw e })
+ )
+
-- -----------------------------------------------------------------------------
-- Asynchronous exceptions
withCString msg $ \cmsg ->
errorBelch cfmt cmsg
-foreign import ccall unsafe errorBelch :: CString -> CString -> IO ()
+foreign import ccall unsafe "RtsMessages.h errorBelch"
+ errorBelch :: CString -> CString -> IO ()
setUncaughtExceptionHandler :: (Exception -> IO ()) -> IO ()
setUncaughtExceptionHandler = writeIORef uncaughtExceptionHandler