Commit dc1fce13 authored by thomie's avatar thomie Committed by Austin Seipp
Browse files

Refer to 'mask' instead of 'block' in Control.Exception

Summary: More thorough version of a75383cd

Test Plan:
change of comments only

[skip ci]

Reviewers: austin, simonmar, ekmett

Reviewed By: austin, ekmett

Subscribers: simonmar, ezyang, carter

Differential Revision: https://phabricator.haskell.org/D239
parent efdf4b9d
......@@ -190,11 +190,11 @@ use:
case use 'catch' or 'catchJust'.
The difference between using 'try' and 'catch' for recovery is that in
'catch' the handler is inside an implicit 'block' (see \"Asynchronous
'catch' the handler is inside an implicit 'mask' (see \"Asynchronous
Exceptions\") which is important when catching asynchronous
exceptions, but when catching other kinds of exception it is
unnecessary. Furthermore it is possible to accidentally stay inside
the implicit 'block' by tail-calling rather than returning from the
the implicit 'mask' by tail-calling rather than returning from the
handler, which is why we recommend using 'try' rather than 'catch' for
ordinary exception recovery.
......@@ -210,7 +210,7 @@ A typical use of 'tryJust' for recovery looks like this:
-- -----------------------------------------------------------------------------
-- Asynchronous exceptions
-- | When invoked inside 'mask', this function allows a blocked
-- | When invoked inside 'mask', this function allows a masked
-- asynchronous exception to be raised, if one exists. It is
-- equivalent to performing an interruptible operation (see
-- #interruptible#), but does not involve any actual blocking.
......@@ -258,7 +258,7 @@ to write something like
> catch (restore (...))
> (\e -> handler)
If you need to unblock asynchronous exceptions again in the exception
If you need to unmask asynchronous exceptions again in the exception
handler, 'restore' can be used there too.
Note that 'try' and friends /do not/ have a similar default, because
......
......@@ -402,8 +402,9 @@ onException io what = io `catchException` \e -> do _ <- what
-- state if the masked thread /blocks/ in certain ways; see
-- "Control.Exception#interruptible".
--
-- Threads created by 'Control.Concurrent.forkIO' inherit the masked
-- state from the parent; that is, to start a thread in blocked mode,
-- 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
......
......@@ -19,23 +19,28 @@ import ghczmprim_GHCziTypes_True_closure;
Exception Primitives
A thread can request that asynchronous exceptions not be delivered
("blocked") for the duration of an I/O computation. The primitive
("masked") for the duration of an I/O computation. The primitives
maskAsyncExceptions# :: IO a -> IO a
is used for this purpose. During a blocked section, asynchronous
exceptions may be unblocked again temporarily:
and
maskUninterruptible# :: IO a -> IO a
are used for this purpose. During a masked section, asynchronous
exceptions may be unmasked again temporarily:
unmaskAsyncExceptions# :: IO a -> IO a
Furthermore, asynchronous exceptions are blocked automatically during
the execution of an exception handler. Both of these primitives
Furthermore, asynchronous exceptions are masked automatically during
the execution of an exception handler. All three of these primitives
leave a continuation on the stack which reverts to the previous
state (blocked or unblocked) on exit.
state (masked interruptible, masked non-interruptible, or unmasked)
on exit.
A thread which wants to raise an exception in another thread (using
killThread#) must block until the target thread is ready to receive
it. The action of unblocking exceptions in a thread will release all
it. The action of unmasking exceptions in a thread will release all
the threads waiting to deliver exceptions to that thread.
NB. there's a bug in here. If a thread is inside an
......@@ -44,7 +49,7 @@ import ghczmprim_GHCziTypes_True_closure;
interruptible operation, and it receives an exception, then the
unsafePerformIO thunk will be updated with a stack object
containing the unmaskAsyncExceptions_ret frame. Later, when
someone else evaluates this thunk, the blocked exception state is
someone else evaluates this thunk, the original masking state is
not restored.
-------------------------------------------------------------------------- */
......@@ -61,7 +66,7 @@ INFO_TABLE_RET(stg_unmaskAsyncExceptionszh_ret, RET_SMALL, W_ info_ptr)
StgTSO_flags(CurrentTSO) = %lobits32(
TO_W_(StgTSO_flags(CurrentTSO)) & ~(TSO_BLOCKEX|TSO_INTERRUPTIBLE));
/* Eagerly raise a blocked exception, if there is one */
/* Eagerly raise a masked exception, if there is one */
if (StgTSO_blocked_exceptions(CurrentTSO) != END_TSO_QUEUE) {
STK_CHK_P_LL (WDS(2), stg_unmaskAsyncExceptionszh_ret_info, R1);
......@@ -192,11 +197,11 @@ stg_unmaskAsyncExceptionszh /* explicit stack */
io = R1;
STK_CHK_P_LL (WDS(4), stg_unmaskAsyncExceptionszh, io);
/* 4 words: one for the unblock frame, 3 for setting up the
/* 4 words: one for the unmask frame, 3 for setting up the
* stack to call maybePerformBlockedException() below.
*/
/* If exceptions are already unblocked, there's nothing to do */
/* If exceptions are already unmasked, there's nothing to do */
if ((TO_W_(StgTSO_flags(CurrentTSO)) & TSO_BLOCKEX) != 0) {
/* avoid growing the stack unnecessarily */
......@@ -214,7 +219,7 @@ stg_unmaskAsyncExceptionszh /* explicit stack */
StgTSO_flags(CurrentTSO) = %lobits32(
TO_W_(StgTSO_flags(CurrentTSO)) & ~(TSO_BLOCKEX|TSO_INTERRUPTIBLE));
/* Eagerly raise a blocked exception, if there is one */
/* Eagerly raise a masked exception, if there is one */
if (StgTSO_blocked_exceptions(CurrentTSO) != END_TSO_QUEUE) {
/*
* We have to be very careful here, as in killThread#, since
......@@ -329,7 +334,7 @@ stg_killMyself
exception = R2;
SAVE_THREAD_STATE();
/* ToDo: what if the current thread is blocking exceptions? */
/* ToDo: what if the current thread is masking exceptions? */
ccall throwToSingleThreaded(MyCapability() "ptr",
target "ptr", exception "ptr");
if (StgTSO_what_next(CurrentTSO) == ThreadKilled::I16) {
......@@ -557,10 +562,10 @@ retry_pop_stack:
handler = StgCatchSTMFrame_handler(Sp);
}
/* Restore the blocked/unblocked state for asynchronous exceptions
/* Restore the masked/unmasked state for asynchronous exceptions
* at the CATCH_FRAME.
*
* If exceptions were unblocked, arrange that they are unblocked
* If exceptions were unmasked, arrange that they are unmasked
* again after executing the handler by pushing an
* unmaskAsyncExceptions_ret stack frame.
*
......@@ -577,7 +582,7 @@ retry_pop_stack:
Sp(0) = stg_unmaskAsyncExceptionszh_ret_info;
}
/* Ensure that async exceptions are blocked when running the handler.
/* Ensure that async exceptions are masked when running the handler.
*/
StgTSO_flags(CurrentTSO) = %lobits32(
TO_W_(StgTSO_flags(CurrentTSO)) | TSO_BLOCKEX | TSO_INTERRUPTIBLE);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment