Executes an IO computation with asynchronous exceptions
masked.
That is, any thread which attempts to raise an exception in the
current thread with
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
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
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
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
forkIOWithUnmask.