unsafeUnmask unmasks even inside uninterruptibleMask
Control.Exception exports
allowInterrupt :: IO ()
allowInterrupt = unsafeUnmask $ return ()
with documentation:
When invoked inside mask
, this function allows a blocked asynchronous exception to be raised, if one exists. It is equivalent to performing an interruptible operation, but does not involve any actual blocking. When called outside mask
, or inside uninterruptibleMask
, this function has no effect.
However, this is not actually true: unsafeUnmask
unmasks exceptions even inside uninterruptibleUnmask
, as the attached test demonstrates (the test uses a foreign call just to have something non-interruptible but still observable; in particular, doing a print
is interruptible because it uses an MVar
under the hood).
I think it is possible to define a better unsafeUnmask
in user-land:
interruptible :: IO a -> IO a
interruptible act = do
st <- getMaskingState
case st of
Unmasked -> act
MaskedInterruptible -> unsafeUnmask act
MaskedUninterruptible -> act
but it still seems to be that we should either (i) change the behaviour of unsafeUnmask, or (ii) provide a version of unsafeUnmask
with the behaviour as described and then change allowInterrupt
to use that new version of unsafeUnmask
, or at the very least (iii) change the documentation.
(One question with the above definition of interruptible
is what happens when we nest mask
and uninterruptibleMask
?)
Trac metadata
Trac field | Value |
---|---|
Version | 7.8.2 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Runtime System |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | simonmar |
Operating system | |
Architecture |