Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finalizer not called with some uses of runSafeP and nested pipes #12

Open
Davorak opened this issue May 4, 2014 · 2 comments
Open

Finalizer not called with some uses of runSafeP and nested pipes #12

Davorak opened this issue May 4, 2014 · 2 comments

Comments

@Davorak
Copy link
Contributor

Davorak commented May 4, 2014

I think there was a Haskell-pipes mailing list discussion that I started about this a while back. I will link it if I find it later, I searched for a few moments with out luck. I thought this should be documented for others to reference since it is often hard to search through mailing lists.

The conclusion as I remember it was the problem came down to C.bracket in runSafeT.

runSafeT :: (MonadCatch m, MonadIO m) => SafeT m r -> m r
runSafeT m = C.bracket
    (liftIO $ newIORef $! Finalizers 0 M.empty)
    (\ioref -> do
        Finalizers _ fs <- liftIO (readIORef ioref)
        mapM snd (M.toDescList fs) )
    (R.runReaderT (unSafeT m))

The problem was really about Control.Monad.Catch and last I heard Edward, Gabriel, and Snoyman where going to put their head together and come up with a better Mona.Catch.

I think Gabriel has also mentioned using an idea that is in the ballpark of "free categories" to handle this type of problem among other things.

Here is the example that fails to close the "tmp2" file.

ghci> runSafeT . runEffect $ readFile' "tmp" >-> writeFile' "tmp2"
{tmp2 open}
{tmp open}
{tmp closed}

I have put the rest of the code in the following gist:
https://gist.github.com/Davorak/f75f6df327cbc4742f16

@christian-marie
Copy link

Did you find that link? Is this still the case? We're using this in some production code and are hoping that this abstraction is not broken.

@Gabriella439
Copy link
Owner

This is the discussion: https://groups.google.com/d/topic/haskell-pipes/kYrol5F4B5M/discussion

I can summarize the discussion by saying:

  • Proxy ... (SafeT IO) is okay
  • SafeT (Proxy ... IO) is not okay

The reason why is that runSafeT uses the MonadCatch interface for the monad beneath it, which does the right thing if the monad beneath it is IO, but does the wrong thing if the monad beneath it is Proxy (because we can't use the MonadCatch interface to call Pipes.Safe.bracket).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants