#7170: Foreign.Concurrent finalizer called twice in some cases
------------------------------+---------------------------------------------
Reporter: joeyadams | Owner:
Type: bug | Status: new
Priority: normal | Component: Runtime System
Version: 7.4.2 | Keywords:
Os: Unknown/Multiple | Architecture: Unknown/Multiple
Failure: Runtime crash | Testcase:
Blockedby: | Blocking:
Related: |
------------------------------+---------------------------------------------
Comment(by joeyadams):
I'm guessing that the problem is in this function from
{{{GHC.ForeignPtr}}}:
{{{
foreignPtrFinalizer :: IORef (Finalizers, [IO ()]) -> IO ()
foreignPtrFinalizer r = do (_, fs) <- readIORef r; sequence_ fs
}}}
This invokes the finalizers, but does not empty out the list. When the
application calls finalizeForeignPtr later, the same list of finalizers is
run again.
While we're at it, this really bothers me:
{{{
finalizeForeignPtr (ForeignPtr _ foreignPtr) = do
(ftype, finalizers) <- readIORef refFinalizers
sequence_ finalizers
writeIORef refFinalizers (ftype, [])
}}}
This isn't thread safe or exception safe. Finalizers can be repeated if
another thread comes along and calls finalizeForeignPtr on the same
pointer, or if a finalizer throws an exception.
A reasonable solution might be to wrap incoming finalizers with this:
{{{
once :: IO () -> IO (IO ())
once io = do
mv <- newMVar io
return $ tryTakeMVar mv >>= maybe (return ()) id
}}}
This way, we don't have to worry about finalizers being called twice.
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/7170#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs