[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