1 {-# OPTIONS_GHC -XNoImplicitPrelude #-}
3 -----------------------------------------------------------------------------
5 -- Module : Control.Exception
6 -- Copyright : (c) The University of Glasgow 2001
7 -- License : BSD-style (see the file libraries/base/LICENSE)
9 -- Maintainer : libraries@haskell.org
10 -- Stability : experimental
11 -- Portability : non-portable (extended exceptions)
13 -- This module provides support for raising and catching both built-in
14 -- and user-defined exceptions.
16 -- In addition to exceptions thrown by 'IO' operations, exceptions may
17 -- be thrown by pure code (imprecise exceptions) or by external events
18 -- (asynchronous exceptions), but may only be caught in the 'IO' monad.
19 -- For more details, see:
21 -- * /A semantics for imprecise exceptions/, by Simon Peyton Jones,
22 -- Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson,
25 -- * /Asynchronous exceptions in Haskell/, by Simon Marlow, Simon Peyton
26 -- Jones, Andy Moran and John Reppy, in /PLDI'01/.
28 -----------------------------------------------------------------------------
30 module Control.Exception (
32 -- * The Exception type
38 Exception(..), -- instance Eq, Ord, Show, Typeable
39 IOException, -- instance Eq, Ord, Show, Typeable
40 ArithException(..), -- instance Eq, Ord, Show, Typeable
41 ArrayException(..), -- instance Eq, Ord, Show, Typeable
43 AsyncException(..), -- instance Eq, Ord, Show, Typeable
45 #if __GLASGOW_HASKELL__ || __HUGS__
50 BlockedOnDeadMVar(..),
51 BlockedIndefinitely(..),
60 -- * Throwing exceptions
61 throwIO, -- :: Exception -> IO a
62 throw, -- :: Exception -> a
63 ioError, -- :: IOError -> IO a
64 #ifdef __GLASGOW_HASKELL__
65 throwTo, -- :: ThreadId -> Exception -> a
68 -- * Catching Exceptions
70 -- |There are several functions for catching and examining
71 -- exceptions; all of them may only be used from within the
74 -- ** The @catch@ functions
75 catch, -- :: IO a -> (Exception -> IO a) -> IO a
76 #if __GLASGOW_HASKELL__ || __HUGS__
79 catchJust, -- :: (Exception -> Maybe b) -> IO a -> (b -> IO a) -> IO a
81 -- ** The @handle@ functions
82 handle, -- :: (Exception -> IO a) -> IO a -> IO a
83 handleJust,-- :: (Exception -> Maybe b) -> (b -> IO a) -> IO a -> IO a
85 -- ** The @try@ functions
86 try, -- :: IO a -> IO (Either Exception a)
87 tryJust, -- :: (Exception -> Maybe b) -> a -> IO (Either b a)
90 -- ** The @evaluate@ function
91 evaluate, -- :: a -> IO a
93 -- ** The @mapException@ function
94 mapException, -- :: (Exception -> Exception) -> a -> a
96 -- * Asynchronous Exceptions
100 -- ** Asynchronous exception control
102 -- |The following two functions allow a thread to control delivery of
103 -- asynchronous exceptions during a critical region.
105 block, -- :: IO a -> IO a
106 unblock, -- :: IO a -> IO a
107 blocked, -- :: IO Bool
109 -- *** Applying @block@ to an exception handler
113 -- *** Interruptible operations
119 assert, -- :: Bool -> a -> a
123 bracket, -- :: IO a -> (a -> IO b) -> (a -> IO c) -> IO ()
124 bracket_, -- :: IO a -> IO b -> IO c -> IO ()
127 finally, -- :: IO a -> IO b -> IO a
130 import Control.Exception.Base
132 #ifdef __GLASGOW_HASKELL__
138 #if __GLASGOW_HASKELL__ || __HUGS__
139 data Handler a = forall e . Exception e => Handler (e -> IO a)
141 catches :: IO a -> [Handler a] -> IO a
142 catches io handlers = io `catch` catchesHandler handlers
144 catchesHandler :: [Handler a] -> SomeException -> IO a
145 catchesHandler handlers e = foldr tryHandler (throw e) handlers
146 where tryHandler (Handler handler) res
147 = case fromException e of
148 Just e' -> handler e'
152 -- -----------------------------------------------------------------------------
153 -- Asynchronous exceptions
157 #AsynchronousExceptions# Asynchronous exceptions are so-called because they arise due to
158 external influences, and can be raised at any point during execution.
159 'StackOverflow' and 'HeapOverflow' are two examples of
160 system-generated asynchronous exceptions.
162 The primary source of asynchronous exceptions, however, is
165 > throwTo :: ThreadId -> Exception -> IO ()
167 'throwTo' (also 'throwDynTo' and 'Control.Concurrent.killThread') allows one
168 running thread to raise an arbitrary exception in another thread. The
169 exception is therefore asynchronous with respect to the target thread,
170 which could be doing anything at the time it receives the exception.
171 Great care should be taken with asynchronous exceptions; it is all too
172 easy to introduce race conditions by the over zealous use of
177 There\'s an implied 'block' around every exception handler in a call
178 to one of the 'catch' family of functions. This is because that is
179 what you want most of the time - it eliminates a common race condition
180 in starting an exception handler, because there may be no exception
181 handler on the stack to handle another exception if one arrives
182 immediately. If asynchronous exceptions are blocked on entering the
183 handler, though, we have time to install a new exception handler
184 before being interrupted. If this weren\'t the default, one would have
185 to write something like
188 > catch (unblock (...))
192 If you need to unblock asynchronous exceptions again in the exception
193 handler, just use 'unblock' as normal.
195 Note that 'try' and friends /do not/ have a similar default, because
196 there is no exception handler in this case. If you want to use 'try'
197 in an asynchronous-exception-safe way, you will need to use
203 Some operations are /interruptible/, which means that they can receive
204 asynchronous exceptions even in the scope of a 'block'. Any function
205 which may itself block is defined as interruptible; this includes
206 'Control.Concurrent.MVar.takeMVar'
207 (but not 'Control.Concurrent.MVar.tryTakeMVar'),
208 and most operations which perform
209 some I\/O with the outside world. The reason for having
210 interruptible operations is so that we can write things like
214 > catch (unblock (...))
218 if the 'Control.Concurrent.MVar.takeMVar' was not interruptible,
220 combination could lead to deadlock, because the thread itself would be
221 blocked in a state where it can\'t receive any asynchronous exceptions.
222 With 'Control.Concurrent.MVar.takeMVar' interruptible, however, we can be
223 safe in the knowledge that the thread can receive exceptions right up
224 until the point when the 'Control.Concurrent.MVar.takeMVar' succeeds.
225 Similar arguments apply for other interruptible operations like
226 'System.IO.openFile'.