
Yes, there's a good reason: it's a bug :). I wrote that code a while ago,
and had a mistaken understanding of how bracket works at the time. Thanks
for noticing this, I'll release a new version shortly.
On Mon, Nov 7, 2016 at 2:30 AM, Viktor Dukhovni
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. _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.