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