C finalizers are reversed during GC
(See also thread starting at http://www.haskell.org/pipermail/libraries/2012-August/018302.html )
The list of finalizers is reversed during GC (cf. rts/sm/MarkWeak.c), which may cause them to run in the wrong order.
The following program reproduces this behaviour.
{-# LANGUAGE ForeignFunctionInterface, MagicHash #-}
import GHC.ForeignPtr
import GHC.Ptr
import System.Mem
-- one should really use own C function rather than this varargs one to avoid
-- possible ABI issues
foreign import ccall "&debugBelch" fun :: FunPtr (Ptr () -> Ptr () -> IO ())
new name = do
p <- newForeignPtr_ (Ptr name)
addForeignPtrFinalizerEnv fun (Ptr "finalizer 1 (%s)\n"#) p
addForeignPtrFinalizerEnv fun (Ptr "finalizer 2 (%s)\n"#) p
return p
main = do
p <- new "p"#
q <- new "q"#
r <- new "r"#
performGC -- collect p. finalizer order: 2, then 1.
print q
performGC -- collect q. finalizer order: 1, then 2.
-- expected order: 2, then 1.
print r
performGC -- collect r. finalizer order: 2, then 1.
Trac metadata
| Trac field | Value |
|---|---|
| Version | 7.6.1-rc1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Runtime System |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture |