Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can exceptions sneak between restore and mask?

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 ...

Right when the client's mask is lifted, but before the end of my restore surrounding it, where an exception could sneak through?

like image 772
Dan Burton Avatar asked May 12 '14 07:05

Dan Burton


1 Answers

Yes, in GHC, when the unmask occurs we eagerly check for blocked exceptions and raise them.

like image 119
Edward Z. Yang Avatar answered Nov 16 '22 22:11

Edward Z. Yang