C finalizer of a finalized ForeignPtr may be called again when RTS shuts down
The C finalizer of a ForeignPtr that was explicitly finalized (finalizeForeignPtr) is sometimes called again when the RTS shuts down.
Expected behaviour:
- The test script (./test.sh) below never stops
Observed behaviour:
- After a while, the test script stops with an error message indicating double free or memory corruption
$ ./test.sh
[1 of 1] Compiling Main ( finalizer_hs.hs, finalizer_hs.o )
Linking finalizer_hs ...
*** Error in `./finalizer_hs': double free or corruption (!prev): 0x00000000010b85e0 ***
./test.sh: line 3: 20482 Aborted (core dumped) ./finalizer_hs +RTS -N
178
File finalizer_hs.hs
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign (Ptr, FunPtr, malloc)
import Foreign.ForeignPtr (newForeignPtr, finalizeForeignPtr)
import Control.Monad (forM, forM_)
foreign import ccall "stdlib.h &free" p_free :: FunPtr (Ptr a -> IO ())
main :: IO ()
main = do
fps <- forM [1 .. 10000] $ \_ -> do
p <- malloc
newForeignPtr p_free (p :: Ptr Int)
forM_ fps finalizeForeignPtr
File test.sh:
ghc finalizer_hs.hs -threaded
CNT=0
while ./finalizer_hs +RTS -N; do CNT=$((CNT+1)); done
echo $CNT
Note: running several instances of ./test.sh concurrently triggers the problem faster
Issue detected on following tested setups:
- Linux 32bit GHC 7.10.2
- Linux 64bit GHC 7.8.3
- Linux 64bit GHC 7.8.4
Trac metadata
| Trac field | Value |
|---|---|
| Version | 7.8.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Runtime System |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | simonmar |
| Operating system | |
| Architecture |