[Haskell-cafe] ResourceT "unmasked" during allocation?

Viktor Dukhovni ietf-dane at dukhovni.org
Mon Nov 7 00:30:59 UTC 2016


I am looking at using ResourceT to manage the acquisiition and
deallocation of network sockets.  In comparing resourceT's `allocate`
with `bracket` I was somewhat perplexed to find that `allocate` in
Control.Monad.Trans.Resource seems to not mask exceptions during
allocation (see "No mask" comment I inserted):

	allocateRIO :: IO a -> (a -> IO ()) -> ResourceT IO (ReleaseKey, a)
	allocateRIO acquire rel = ResourceT $ \istate -> liftIO $ E.mask $ \restore -> do
	    a <- restore acquire
            --   ^^^ No mask ^^^
	    key <- register' istate $ rel a
	    return (key, a)

	allocate :: MonadResource m
		 => IO a -- ^ allocate
		 -> (a -> IO ()) -- ^ free resource
		 -> m (ReleaseKey, a)
	allocate a = liftResourceT . allocateRIO a

By contrast in Exception.Base we see that `bracket` masks
the initialization action:

	bracket before after thing =
	  mask $ \restore -> do
	    a <- before
            --   ^^^ masked! ^^^
	    r <- restore (thing a) `onException` after a
	    _ <- after a
	    return r

This seems to suggest that ResourceT is more exposes to resource
leaks via asynchronous exceptions.  Say if a file descriptor is a
allocated, but an exception interrupts "allocate" before it can
register the resource.

Perhaps I am missing something, or there are good reasons for
the difference in approach.  Can anyone shed some light on the
reason why ResourceT differs (seemingly) from bracket in this
regard.

-- 
	Viktor.


More information about the Haskell-Cafe mailing list