Admin message

Due to a large amount of spam we do not allow new users to create repositories, they are "external" users. If you are a new user and want to create a repository, for example for forking GHC, open a new issue on ghc/ghc using the "get-verified" issue template

unsafeUnmask unmasks even inside uninterruptibleMask
Control.Exception exports ```hs 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: ```hs 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`?) <details><summary>Trac metadata</summary> | 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 | | </details> <!-- {"blocked_by":[],"summary":"unsafeUnmask unmasks even inside uninterruptibleMask","status":"New","operating_system":"","component":"Runtime System","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"OwnedBy","contents":"simonmar"},"version":"7.8.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["simonmar"],"type":"Bug","description":"Control.Exception exports\r\n\r\n{{{#!hs\r\nallowInterrupt :: IO ()\r\nallowInterrupt = unsafeUnmask $ return ()\r\n}}}\r\n\r\nwith documentation:\r\n\r\n''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.''\r\n\r\nHowever, 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).\r\n\r\nI think it is possible to define a better `unsafeUnmask` in user-land:\r\n\r\n{{{#!hs\r\ninterruptible :: IO a -> IO a\r\ninterruptible act = do\r\n st <- getMaskingState\r\n case st of\r\n Unmasked -> act\r\n MaskedInterruptible -> unsafeUnmask act\r\n MaskedUninterruptible -> act\r\n}}}\r\n\r\nbut 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. \r\n\r\n(One question with the above definition of `interruptible` is what happens when we ''nest'' `mask` and `uninterruptibleMask`?)","type_of_failure":"OtherFailure","blocking":[]} -->
issue