[Haskell-cafe] Re: Asynchronous exception wormholes kill
marlowsd at gmail.com
Wed Apr 7 11:49:44 EDT 2010
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
>> 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
I did implement the nesting levels version first, and when adding
non-interruptibility to the mix things got quite hairy.
More information about the Libraries