1 {-# LANGUAGE NoImplicitPrelude, DeriveDataTypeable, MagicHash #-}
2 {-# OPTIONS_GHC -funbox-strict-fields #-}
3 {-# OPTIONS_HADDOCK hide #-}
4 -----------------------------------------------------------------------------
6 -- Module : GHC.IO.Exception
7 -- Copyright : (c) The University of Glasgow, 2009
8 -- License : see libraries/base/LICENSE
10 -- Maintainer : libraries@haskell.org
11 -- Stability : internal
12 -- Portability : non-portable
14 -- IO-related Exception types and functions
16 -----------------------------------------------------------------------------
18 module GHC.IO.Exception (
19 BlockedIndefinitelyOnMVar(..), blockedIndefinitelyOnMVar,
20 BlockedIndefinitelyOnSTM(..), blockedIndefinitelyOnSTM,
23 AsyncException(..), stackOverflow, heapOverflow,
45 import GHC.IO.Handle.Types
46 import Foreign.C.Types
48 import Data.Typeable ( Typeable )
50 -- ------------------------------------------------------------------------
51 -- Exception datatypes and operations
53 -- |The thread is blocked on an @MVar@, but there are no other references
54 -- to the @MVar@ so it can't ever continue.
55 data BlockedIndefinitelyOnMVar = BlockedIndefinitelyOnMVar
58 instance Exception BlockedIndefinitelyOnMVar
60 instance Show BlockedIndefinitelyOnMVar where
61 showsPrec _ BlockedIndefinitelyOnMVar = showString "thread blocked indefinitely in an MVar operation"
63 blockedIndefinitelyOnMVar :: SomeException -- for the RTS
64 blockedIndefinitelyOnMVar = toException BlockedIndefinitelyOnMVar
68 -- |The thread is waiting to retry an STM transaction, but there are no
69 -- other references to any @TVar@s involved, so it can't ever continue.
70 data BlockedIndefinitelyOnSTM = BlockedIndefinitelyOnSTM
73 instance Exception BlockedIndefinitelyOnSTM
75 instance Show BlockedIndefinitelyOnSTM where
76 showsPrec _ BlockedIndefinitelyOnSTM = showString "thread blocked indefinitely in an STM transaction"
78 blockedIndefinitelyOnSTM :: SomeException -- for the RTS
79 blockedIndefinitelyOnSTM = toException BlockedIndefinitelyOnSTM
83 -- |There are no runnable threads, so the program is deadlocked.
84 -- The @Deadlock@ exception is raised in the main thread only.
85 data Deadlock = Deadlock
88 instance Exception Deadlock
90 instance Show Deadlock where
91 showsPrec _ Deadlock = showString "<<deadlock>>"
95 -- |'assert' was applied to 'False'.
96 data AssertionFailed = AssertionFailed String
99 instance Exception AssertionFailed
101 instance Show AssertionFailed where
102 showsPrec _ (AssertionFailed err) = showString err
106 -- |Asynchronous exceptions.
109 -- ^The current thread\'s stack exceeded its limit.
110 -- Since an exception has been raised, the thread\'s stack
111 -- will certainly be below its limit again, but the
112 -- programmer should take remedial action
115 -- ^The program\'s heap is reaching its limit, and
116 -- the program should take action to reduce the amount of
117 -- live data it has. Notes:
119 -- * It is undefined which thread receives this exception.
121 -- * GHC currently does not throw 'HeapOverflow' exceptions.
123 -- ^This exception is raised by another thread
124 -- calling 'Control.Concurrent.killThread', or by the system
125 -- if it needs to terminate the thread for some
128 -- ^This exception is raised by default in the main thread of
129 -- the program when the user requests to terminate the program
130 -- via the usual mechanism(s) (e.g. Control-C in the console).
131 deriving (Eq, Ord, Typeable)
133 instance Exception AsyncException
135 -- | Exceptions generated by array operations
137 = IndexOutOfBounds String
138 -- ^An attempt was made to index an array outside
139 -- its declared bounds.
140 | UndefinedElement String
141 -- ^An attempt was made to evaluate an element of an
142 -- array that had not been initialized.
143 deriving (Eq, Ord, Typeable)
145 instance Exception ArrayException
147 stackOverflow, heapOverflow :: SomeException -- for the RTS
148 stackOverflow = toException StackOverflow
149 heapOverflow = toException HeapOverflow
151 instance Show AsyncException where
152 showsPrec _ StackOverflow = showString "stack overflow"
153 showsPrec _ HeapOverflow = showString "heap overflow"
154 showsPrec _ ThreadKilled = showString "thread killed"
155 showsPrec _ UserInterrupt = showString "user interrupt"
157 instance Show ArrayException where
158 showsPrec _ (IndexOutOfBounds s)
159 = showString "array index out of range"
160 . (if not (null s) then showString ": " . showString s
162 showsPrec _ (UndefinedElement s)
163 = showString "undefined array element"
164 . (if not (null s) then showString ": " . showString s
167 -- -----------------------------------------------------------------------------
170 -- We need it here because it is used in ExitException in the
171 -- Exception datatype (above).
173 -- | Defines the exit codes that a program can return.
175 = ExitSuccess -- ^ indicates successful termination;
177 -- ^ indicates program failure with an exit code.
178 -- The exact interpretation of the code is
179 -- operating-system dependent. In particular, some values
180 -- may be prohibited (e.g. 0 on a POSIX-compliant system).
181 deriving (Eq, Ord, Read, Show, Typeable)
183 instance Exception ExitCode
185 ioException :: IOException -> IO a
186 ioException err = throwIO err
188 -- | Raise an 'IOError' in the 'IO' monad.
189 ioError :: IOError -> IO a
190 ioError = ioException
192 -- ---------------------------------------------------------------------------
195 -- | The Haskell 98 type for exceptions in the 'IO' monad.
196 -- Any I\/O operation may raise an 'IOError' instead of returning a result.
197 -- For a more general type of exception, including also those that arise
198 -- in pure code, see "Control.Exception.Exception".
200 -- In Haskell 98, this is an opaque type.
201 type IOError = IOException
203 -- |Exceptions that occur in the @IO@ monad.
204 -- An @IOException@ records a more specific error type, a descriptive
205 -- string and maybe the handle that was used when the error was
209 ioe_handle :: Maybe Handle, -- the handle used by the action flagging
211 ioe_type :: IOErrorType, -- what it was.
212 ioe_location :: String, -- location.
213 ioe_description :: String, -- error type specific information.
214 ioe_errno :: Maybe CInt, -- errno leading to this error, if any.
215 ioe_filename :: Maybe FilePath -- filename the error is related to.
219 instance Exception IOException
221 instance Eq IOException where
222 (IOError h1 e1 loc1 str1 en1 fn1) == (IOError h2 e2 loc2 str2 en2 fn2) =
223 e1==e2 && str1==str2 && h1==h2 && loc1==loc2 && en1==en2 && fn1==fn2
225 -- | An abstract type that contains a value for each variant of 'IOError'.
237 | UnsatisfiedConstraints
244 | UnsupportedOperation
249 instance Eq IOErrorType where
250 x == y = getTag x ==# getTag y
252 instance Show IOErrorType where
256 AlreadyExists -> "already exists"
257 NoSuchThing -> "does not exist"
258 ResourceBusy -> "resource busy"
259 ResourceExhausted -> "resource exhausted"
261 IllegalOperation -> "illegal operation"
262 PermissionDenied -> "permission denied"
263 UserError -> "user error"
264 HardwareFault -> "hardware fault"
265 InappropriateType -> "inappropriate type"
266 Interrupted -> "interrupted"
267 InvalidArgument -> "invalid argument"
268 OtherError -> "failed"
269 ProtocolError -> "protocol error"
270 ResourceVanished -> "resource vanished"
271 SystemError -> "system error"
272 TimeExpired -> "timeout"
273 UnsatisfiedConstraints -> "unsatisified constraints" -- ultra-precise!
274 UnsupportedOperation -> "unsupported operation"
276 -- | Construct an 'IOError' value with a string describing the error.
277 -- The 'fail' method of the 'IO' instance of the 'Monad' class raises a
278 -- 'userError', thus:
280 -- > instance Monad IO where
282 -- > fail s = ioError (userError s)
284 userError :: String -> IOError
285 userError str = IOError Nothing UserError "" str Nothing Nothing
287 -- ---------------------------------------------------------------------------
290 instance Show IOException where
291 showsPrec p (IOError hdl iot loc s _ fn) =
293 Nothing -> case hdl of
295 Just h -> showsPrec p h . showString ": "
296 Just name -> showString name . showString ": ") .
299 _ -> showString loc . showString ": ") .
303 _ -> showString " (" . showString s . showString ")")
305 assertError :: Addr# -> Bool -> a -> a
306 assertError str predicate v
308 | otherwise = throw (AssertionFailed (untangle str "Assertion failed"))
310 unsupportedOperation :: IOError
311 unsupportedOperation =
312 (IOError Nothing UnsupportedOperation ""
313 "Operation is not supported" Nothing Nothing)
316 (untangle coded message) expects "coded" to be of the form
319 location message details
321 untangle :: Addr# -> String -> String
322 untangle coded message
329 coded_str = unpackCStringUtf8# coded
332 = case (span not_bar coded_str) of { (loc, rest) ->
334 ('|':det) -> (loc, ' ' : det)