Asynchronous exception wormholes kill modularity

Tyson Whitehead twhitehead at
Thu Apr 8 16:20:25 EDT 2010

On March 26, 2010 15:51:42 Isaac Dupree wrote:
> On 03/25/10 12:36, Simon Marlow wrote:
> > I'd also be amenable to having block/unblock count nesting levels
> > instead, I don't think it would be too hard to implement and it wouldn't
> > require any changes at the library level.
> Wasn't there a reason that it didn't nest?
> I think it was that operations that block-as-in-takeMVar, for an
> unbounded length of time, are always supposed to C.Exception.unblock and
> in fact be unblocked within that operation.  Otherwise the thread might
> never receive its asynchronous exceptions.

If I'm understanding correctly here, it would be nice if you could just go

unmask :: IO a -> IO a

and always have asynchronous exceptions on for the duration of IO a.

One solution might be if unmask always enabled asynchronous exception, but, in 
a masked context, stopped them from propagating beyond the boundary of the IO 
a action by re-queueing them be re-raised when next allowed.

Of course you've then got the problem of umask having to produce a valid value 
even when IO a was aborted, so you would have to go with something like

unmask :: a -> IO a -> IO a

where the first a gets returned if the IO a computation gets aborted by an 
exception.  The original problem code would then go from

modifyMVar_ :: MVar a -> (a -> IO a) -> IO ()
modifyMVar_ m io =
  block $ do
    a  <- takeMVar m
    a' <- unblock (io a) `onException` putMVar m a
    putMVar m a'


modifyMVar_ :: MVar a -> (a -> IO a) -> IO ()
modifyMVar_ m io =
  block $ do
    a  <- takeMVar m
    a' <- unmask a (io a)
    putMVar m a'

Cheers!  -Tyson
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part.
Url :

More information about the Libraries mailing list