Suppose I have some code written like so:

import Control.Exception (bracketOnError, finally, mask) import Client (acquireB, releaseB, doStuff) -- theoretical import MyStuff (preliminary, doMoreStuff) -- theoretical clientAction = bracketOnError acquireB releaseB $ \b -> doStuff b return (b, releaseB b) myAction = mask $ \restore -> a <- preliminary (thing, releaseThing) <- restore clientAction doMoreStuff a thing `finally` releaseThing

I have to do some preliminary stuff, my client acquires b and then has to doStuff with b , and then I have to doMoreStuff with b . And b needs to be released, even if an asynchronous exception occurs. But I don't know how to release b , so my client tells me how. Written this way, we are both prepared to release b if an exception happens during "our" code.

My question is this: Is it ever possible for an async exception to cause releaseB not to be performed? Specifically, is there a gap between "my code" and "my client's code" where an async exception can squeeze in? Let me inline clientAction and bracketOnException to explain.

myAction = mask $ \restore -> do a <- preliminary (thing, releaseThing) <- restore $ mask $ \restore2 -> do b <- acquireB restore2 (doStuff b >> return (b, releaseB b)) `onException` releaseB b doMoreStuff a thing `finally` releaseThing

The concern is this: is there a moment right here

... restore $ mask ...