unsafeUnmask unmasks even inside uninterruptibleMask
allowInterrupt :: IO () allowInterrupt = unsafeUnmask $ return ()
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
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