On 07/04/2010 16:20, Sittampalam, Ganesh wrote:
Simon Marlow wrote:

I came to the conclusion that counting nesting layers doesn't solve
the problem: the wormhole still exists in the form of nested unmasks.
That is, a library function could always escape out of a masked
context by writing

    unmask $ unmask $ unmask $ ...

enough times.
[...]
mask :: ((IO a ->  IO a) ->  IO b) ->  IO b
mask io = do
    b<- blocked
    if b
       then io id
       else block $ io unblock

to be used like this:

a `finally` b =
    mask $ \restore ->  do
      r<- restore a `onException` b
      b
      return r

So the property we want is that if I call a library function

    mask $ \_ ->  call_library_function

then there's no way that the library function can unmask exceptions.
If all they have access to is 'mask', then that's true.
[...]
It's possible to mis-use the API, e.g.

    getUnmask = mask return

Given that both the "simple" mask/unmask and your alternate proposal
have backdoors, is the extra complexity really worth it?

The answer is yes, for a couple of reasons.

 1. this version really is safer than mask/unmask that count
    nesting levels.  If the caller is playing by the rules,
    then a library function can't unmask exceptions.  The
    responsibility not to screw up is in the hands of the
    caller, not the callee: that's an improvement.

 2. in this version more of the code is in Haskell, and
    the primitives and RTS implementation are simpler.  So
    actually I consider this less complex than counting
    nesting levels.

I did implement the nesting levels version first, and when adding non-interruptibility to the mix things got quite hairy.

Cheers,
        Simon
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to