{-# LANGUAGE Unsafe #-} {-# LANGUAGE NoImplicitPrelude , BangPatterns , RankNTypes , MagicHash , UnboxedTuples #-} {-# OPTIONS_GHC -funbox-strict-fields #-} {-# OPTIONS_HADDOCK hide #-} ----------------------------------------------------------------------------- -- | -- Module : GHC.IO -- Copyright : (c) The University of Glasgow 1994-2002 -- License : see libraries/base/LICENSE -- -- Maintainer : [email protected] -- Stability : internal -- Portability : non-portable (GHC Extensions) -- -- Definitions for the 'IO' monad and its friends. -- ----------------------------------------------------------------------------- module GHC.IO ( IO(..), unIO, failIO, liftIO, mplusIO, unsafePerformIO, unsafeInterleaveIO, unsafeDupablePerformIO, unsafeDupableInterleaveIO, noDuplicate, -- To and from from ST stToIO, ioToST, unsafeIOToST, unsafeSTToIO, FilePath, catchException, catchAny, throwIO, mask, mask_, uninterruptibleMask, uninterruptibleMask_, MaskingState(..), getMaskingState, unsafeUnmask, interruptible, onException, bracket, finally, evaluate ) where import GHC.Base import GHC.ST import GHC.Exception import GHC.Show import GHC.IO.Unsafe import {-# SOURCE #-} GHC.IO.Exception ( userError, IOError ) -- --------------------------------------------------------------------------- -- The IO Monad {- The IO Monad is just an instance of the ST monad, where the state is the real world. We use the exception mechanism (in GHC.Exception) to implement IO exceptions. NOTE: The IO representation is deeply wired in to various parts of the system. The following list may or may not be exhaustive: Compiler - types of various primitives in PrimOp.lhs RTS - forceIO (StgMiscClosures.hc) - catchzh_fast, (un)?blockAsyncExceptionszh_fast, raisezh_fast (Exceptions.hc) - raiseAsync (Schedule.c) Prelude - GHC.IO.lhs, and several other places including GHC.Exception.lhs. Libraries - parts of hslibs/lang. --SDM -} liftIO :: IO a -> State# RealWorld -> STret RealWorld a liftIO (IO m) = \s -> case m s of (# s', r #) -> STret s' r failIO :: String -> IO a failIO s = IO (raiseIO# (toException (userError s))) -- --------------------------------------------------------------------------- -- Coercions between IO and ST -- | A monad transformer embedding strict state transformers in the 'IO' -- monad. The 'RealWorld' parameter indicates that the internal state -- used by the 'ST' computation is a special one supplied by the 'IO' -- monad, and thus distinct from those used by invocations of 'runST'. stToIO :: ST RealWorld a -> IO a stToIO (ST m) = IO m ioToST :: IO a -> ST RealWorld a ioToST (IO m) = (ST m) -- This relies on IO and ST having the same representation modulo the -- constraint on the type of the state -- unsafeIOToST :: IO a -> ST s a unsafeIOToST (IO io) = ST $ \ s -> (unsafeCoerce# io) s unsafeSTToIO :: ST s a -> IO a unsafeSTToIO (ST m) = IO (unsafeCoerce# m) -- ----------------------------------------------------------------------------- -- | File and directory names are values of type 'String', whose precise -- meaning is operating system dependent. Files can be opened, yielding a -- handle which can then be used to operate on the contents of that file. type FilePath = String -- ----------------------------------------------------------------------------- -- Primitive catch and throwIO {- catchException used to handle the passing around of the state to the action and the handler. This turned out to be a bad idea - it meant that we had to wrap both arguments in thunks so they could be entered as normal (remember IO returns an unboxed pair...). Now catch# has type catch# :: IO a -> (b -> IO a) -> IO a (well almost; the compiler doesn't know about the IO newtype so we have to work around that in the definition of catchException below). -} -- | Catch an exception in the 'IO' monad. -- -- Note that this function is /strict/ in the action. That is, -- @catchException undefined b == _|_@. See #exceptions_and_strictness# -- for details. catchException :: Exception e => IO a -> (e -> IO a) -> IO a catchException (IO io) handler = IO $ catch# io handler' where handler' e = case fromException e of Just e' -> unIO (handler e') Nothing -> raiseIO# e -- | Catch any 'Exception' type in the 'IO' monad. -- -- Note that this function is /strict/ in the action. That is, -- @catchException undefined b == _|_@. See #exceptions_and_strictness# for -- details. catchAny :: IO a -> (forall e . Exception e => e -> IO a) -> IO a catchAny (IO io) handler = IO $ catch# io handler' where handler' (SomeException e) = unIO (handler e) mplusIO :: IO a -> IO a -> IO a mplusIO m n = m `catchIOError` \ _ -> n where catchIOError :: IO a -> (IOError -> IO a) -> IO a catchIOError = catchException -- | A variant of 'throw' that can only be used within the 'IO' monad. -- -- Although 'throwIO' has a type that is an instance of the type of 'throw', the -- two functions are subtly different: -- -- > throw e `seq` x ===> throw e -- > throwIO e `seq` x ===> x -- -- The first example will cause the exception @e@ to be raised, -- whereas the second one won\'t. In fact, 'throwIO' will only cause -- an exception to be raised when it is used within the 'IO' monad. -- The 'throwIO' variant should be used in preference to 'throw' to -- raise an exception within the 'IO' monad because it guarantees -- ordering with respect to other 'IO' operations, whereas 'throw' -- does not. throwIO :: Exception e => e -> IO a throwIO e = IO (raiseIO# (toException e)) -- ----------------------------------------------------------------------------- -- Controlling asynchronous exception delivery -- Applying 'block' to a computation will -- execute that computation with asynchronous exceptions -- /blocked/. That is, any thread which -- attempts to raise an exception in the current thread with 'Control.Exception.throwTo' will be -- blocked until asynchronous exceptions are unblocked again. There\'s -- no need to worry about re-enabling asynchronous exceptions; that is -- done automatically on exiting the scope of -- 'block'. -- -- Threads created by 'Control.Concurrent.forkIO' inherit the blocked -- state from the parent; that is, to start a thread in blocked mode, -- use @block $ forkIO ...@. This is particularly useful if you need to -- establish an exception handler in the forked thread before any -- asynchronous exceptions are received. block :: IO a -> IO a block (IO io) = IO $ maskAsyncExceptions# io -- To re-enable asynchronous exceptions inside the scope of -- 'block', 'unblock' can be -- used. It scopes in exactly the same way, so on exit from -- 'unblock' asynchronous exception delivery will -- be disabled again. unblock :: IO a -> IO a unblock = unsafeUnmask unsafeUnmask :: IO a -> IO a unsafeUnmask (IO io) = IO $ unmaskAsyncExceptions# io -- | Allow asynchronous exceptions to be raised even inside 'mask', making -- the operation interruptible (see the discussion of "Interruptible operations" -- in 'Control.Exception'). -- -- When called outside 'mask', or inside 'uninterruptibleMask', this -- function has no effect. -- -- @since 4.9.0.0 interruptible :: IO a -> IO a interruptible act = do st <- getMaskingState case st of Unmasked -> act MaskedInterruptible -> unsafeUnmask act MaskedUninterruptible -> act blockUninterruptible :: IO a -> IO a blockUninterruptible (IO io) = IO $ maskUninterruptible# io -- | Describes the behaviour of a thread when an asynchronous -- exception is received. data MaskingState = Unmasked -- ^ asynchronous exceptions are unmasked (the normal state) | MaskedInterruptible -- ^ the state during 'mask': asynchronous exceptions are masked, but blocking operations may still be interrupted | MaskedUninterruptible -- ^ the state during 'uninterruptibleMask': asynchronous exceptions are masked, and blocking operations may not be interrupted deriving (Eq,Show) -- | Returns the 'MaskingState' for the current thread. getMaskingState :: IO MaskingState getMaskingState = IO $ \s -> case getMaskingState# s of (# s', i #) -> (# s', case i of 0# -> Unmasked 1# -> MaskedUninterruptible _ -> MaskedInterruptible #) onException :: IO a -> IO b -> IO a onException io what = io `catchException` \e -> do _ <- what throwIO (e :: SomeException) -- | Executes an IO computation with asynchronous -- exceptions /masked/. That is, any thread which attempts to raise -- an exception in the current thread with 'Control.Exception.throwTo' -- will be blocked until asynchronous exceptions are unmasked again. -- -- The argument passed to 'mask' is a function that takes as its -- argument another function, which can be used to restore the -- prevailing masking state within the context of the masked -- computation. For example, a common way to use 'mask' is to protect -- the acquisition of a resource: -- -- > mask $ \restore -> do -- > x <- acquire -- > restore (do_something_with x) `onException` release -- > release -- -- This code guarantees that @acquire@ is paired with @release@, by masking -- asynchronous exceptions for the critical parts. (Rather than write -- this code yourself, it would be better to use -- 'Control.Exception.bracket' which abstracts the general pattern). -- -- Note that the @restore@ action passed to the argument to 'mask' -- does not necessarily unmask asynchronous exceptions, it just -- restores the masking state to that of the enclosing context. Thus -- if asynchronous exceptions are already masked, 'mask' cannot be used -- to unmask exceptions again. This is so that if you call a library function -- with exceptions masked, you can be sure that the library call will not be -- able to unmask exceptions again. If you are writing library code and need -- to use asynchronous exceptions, the only way is to create a new thread; -- see 'Control.Concurrent.forkIOWithUnmask'. -- -- Asynchronous exceptions may still be received while in the masked -- state if the masked thread /blocks/ in certain ways; see -- "Control.Exception#interruptible". -- -- Threads created by 'Control.Concurrent.forkIO' inherit the -- 'MaskingState' from the parent; that is, to start a thread in the -- 'MaskedInterruptible' state, -- use @mask_ $ forkIO ...@. This is particularly useful if you need -- to establish an exception handler in the forked thread before any -- asynchronous exceptions are received. To create a a new thread in -- an unmasked state use 'Control.Concurrent.forkIOUnmasked'. -- mask :: ((forall a. IO a -> IO a) -> IO b) -> IO b -- | Like 'mask', but does not pass a @restore@ action to the argument. mask_ :: IO a -> IO a -- | Like 'mask', but the masked computation is not interruptible (see -- "Control.Exception#interruptible"). THIS SHOULD BE USED WITH -- GREAT CARE, because if a thread executing in 'uninterruptibleMask' -- blocks for any reason, then the thread (and possibly the program, -- if this is the main thread) will be unresponsive and unkillable. -- This function should only be necessary if you need to mask -- exceptions around an interruptible operation, and you can guarantee -- that the interruptible operation will only block for a short period -- of time. -- uninterruptibleMask :: ((forall a. IO a -> IO a) -> IO b) -> IO b -- | Like 'uninterruptibleMask', but does not pass a @restore@ action -- to the argument. uninterruptibleMask_ :: IO a -> IO a mask_ io = mask $ \_ -> io mask io = do b <- getMaskingState case b of Unmasked -> block $ io unblock MaskedInterruptible -> io block MaskedUninterruptible -> io blockUninterruptible uninterruptibleMask_ io = uninterruptibleMask $ \_ -> io uninterruptibleMask io = do b <- getMaskingState case b of Unmasked -> blockUninterruptible $ io unblock MaskedInterruptible -> blockUninterruptible $ io block MaskedUninterruptible -> io blockUninterruptible bracket :: 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 bracket before after thing = mask $ \restore -> do a <- before r <- restore (thing a) `onException` after a _ <- after a return r finally :: IO a -- ^ computation to run first -> IO b -- ^ computation to run afterward (even if an exception -- was raised) -> IO a -- returns the value from the first computation a `finally` sequel = mask $ \restore -> do r <- restore a `onException` sequel _ <- sequel return r -- | Evaluate the argument to weak head normal form. -- -- 'evaluate' is typically used to uncover any exceptions that a lazy value -- may contain, and possibly handle them. -- -- 'evaluate' only evaluates to /weak head normal form/. If deeper -- evaluation is needed, the @force@ function from @Control.DeepSeq@ -- may be handy: -- -- > evaluate $ force x -- -- There is a subtle difference between @'evaluate' x@ and @'return' '$!' x@, -- analogous to the difference between 'throwIO' and 'throw'. If the lazy -- value @x@ throws an exception, @'return' '$!' x@ will fail to return an -- 'IO' action and will throw an exception instead. @'evaluate' x@, on the -- other hand, always produces an 'IO' action; that action will throw an -- exception upon /execution/ iff @x@ throws an exception upon /evaluation/. -- -- The practical implication of this difference is that due to the -- /imprecise exceptions/ semantics, -- -- > (return $! error "foo") >> error "bar" -- -- may throw either @"foo"@ or @"bar"@, depending on the optimizations -- performed by the compiler. On the other hand, -- -- > evaluate (error "foo") >> error "bar" -- -- is guaranteed to throw @"foo"@. -- -- The rule of thumb is to use 'evaluate' to force or handle exceptions in -- lazy values. If, on the other hand, you are forcing a lazy value for -- efficiency reasons only and do not care about exceptions, you may -- use @'return' '$!' x@. evaluate :: a -> IO a evaluate a = IO $ \s -> seq# a s -- NB. see #2273, #5129 {- $exceptions_and_strictness Laziness can interact with @catch@-like operations in non-obvious ways (see, e.g. GHC Trac #11555). For instance, consider these subtly-different examples, > test1 = Control.Exception.catch (error "uh oh") (\(_ :: SomeException) -> putStrLn "it failed") > > test2 = GHC.IO.catchException (error "uh oh") (\(_ :: SomeException) -> putStrLn "it failed") While the first case is always guaranteed to print "it failed", the behavior of @test2@ may vary with optimization level. The unspecified behavior of @test2@ is due to the fact that GHC may assume that 'catchException' (and the 'catch#' primitive operation which it is built upon) is strict in its first argument. This assumption allows the compiler to better optimize @catchException@ calls at the expense of deterministic behavior when the action may be bottom. Namely, the assumed strictness means that exceptions thrown while evaluating the action-to-be-executed may not be caught; only exceptions thrown during execution of the action will be handled by the exception handler. Since this strictness is a small optimization and may lead to surprising results, all of the @catch@ and @handle@ variants offered by "Control.Exception" are lazy in their first argument. If you are certain that that the action to be executed won't bottom in performance-sensitive code, you might consider using 'GHC.IO.catchException' or 'GHC.IO.catchAny' for a small speed-up. -}