{-# LANGUAGE Unsafe #-} {-# LANGUAGE NoImplicitPrelude , BangPatterns , RankNTypes , MagicHash , ScopedTypeVariables , 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 : cvs-ghc@haskell.org -- 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, catch, 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.hs RTS - forceIO (StgStartup.cmm) - catchzh_fast, (un)?blockAsyncExceptionszh_fast, raisezh_fast (Exception.cmm) - raiseAsync (RaiseAsync.c) Prelude - GHC.IO.hs, and several other places including GHC.Exception.hs. 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 -- | Embed a strict state transformer in an 'IO' -- action. 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 -- | Convert an 'IO' action into an 'ST' action. The type of the result -- is constrained to use a 'RealWorld' state, and therefore the result cannot -- be passed to 'runST'. ioToST :: IO a -> ST RealWorld a ioToST (IO m) = (ST m) -- | Convert an 'IO' action to an 'ST' action. -- 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 -- | Convert an 'ST' action to an 'IO' action. -- This relies on 'IO' and 'ST' having the same representation modulo the -- constraint on the type of the state. -- -- For an example demonstrating why this is unsafe, see -- https://mail.haskell.org/pipermail/haskell-cafe/2009-April/060719.html 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/catch 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 catch 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 handler = catch io handler -- | This is the simplest of the exception-catching functions. It -- takes a single argument, runs it, and if an exception is raised -- the \"handler\" is executed, with the value of the exception passed as an -- argument. Otherwise, the result is returned as normal. For example: -- -- > catch (readFile f) -- > (\e -> do let err = show (e :: IOException) -- > hPutStr stderr ("Warning: Couldn't open " ++ f ++ ": " ++ err) -- > return "") -- -- Note that we have to give a type signature to @e@, or the program -- will not typecheck as the type is ambiguous. While it is possible -- to catch exceptions of any type, see the section \"Catching all -- exceptions\" (in "Control.Exception") for an explanation of the problems with doing so. -- -- For catching exceptions in pure (non-'IO') expressions, see the -- function 'evaluate'. -- -- Note that due to Haskell\'s unspecified evaluation order, an -- expression may throw one of several possible exceptions: consider -- the expression @(error \"urk\") + (1 \`div\` 0)@. Does -- the expression throw -- @ErrorCall \"urk\"@, or @DivideByZero@? -- -- The answer is \"it might throw either\"; the choice is -- non-deterministic. If you are catching any type of exception then you -- might catch either. If you are calling @catch@ with type -- @IO Int -> (ArithException -> IO Int) -> IO Int@ then the handler may -- get run with @DivideByZero@ as an argument, or an @ErrorCall \"urk\"@ -- exception may be propogated further up. If you call it again, you -- might get a the opposite behaviour. This is ok, because 'catch' is an -- 'IO' computation. -- catch :: Exception e => IO a -- ^ The computation to run -> (e -> IO a) -- ^ Handler to invoke if an exception is raised -> IO a -- See #exceptions_and_strictness#. catch (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, -- @catchAny 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) -- Using catchException here means that if `m` throws an -- 'IOError' /as an imprecise exception/, we will not catch -- it. No one should really be doing that anyway. mplusIO :: IO a -> IO a -> IO a mplusIO m n = m `catchException` \ (_ :: IOError) -> n -- | 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 -- ^ @since 4.3.0.0 , Show -- ^ @since 4.3.0.0 ) -- | 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 new thread in -- an unmasked state use 'Control.Concurrent.forkIOWithUnmask'. -- 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 and #13330). 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 @test1@ will print "it failed", @test2@ will print "uh oh". When using 'catchException', exceptions thrown while evaluating the action-to-be-executed will 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" use 'catch' rather than 'catchException'. -}