Fail: <<loop>> from finalizers and stuff
Sven Moritz Hallberg
pesco at gmx.de
Sun Jul 4 18:53:32 EDT 2004
Dear Foreign Function Interface,
why does a program like the following fail with a "<<loop>>" exception
(using GHC 6.2 on MacOS X)?
-----snip-----
import Foreign
main =
do
f <- mkFinPtr finalizer
fp <- newForeignPtr f nullPtr
putStrLn "Hello World"
finalizer ptr = putStrLn ("Finalize "++show ptr++".")
foreign import ccall "wrapper"
mkFinPtr :: (Ptr () -> IO ()) -> IO (FinalizerPtr ())
-----snap-----
Also, does the use of a "wrapper" import constitute a callback from C
in the sense of the following statement?
"Whether a finalizer may call back into the Haskell system is system
dependent. Portable code may not rely on such callbacks."
I.e. is the above code non-portable?
Why is the ForeignPtr interface constrained to finalizers that are
FunPtrs at all? I want to touch a ForeignPtr from another's finalizer
to satisfy a liveness dependency (as suggested in the spec). What is
the best way to do this?
Suppose I have:
-----snip-----
type Thing = Ptr ()
type Subthing = Ptr ()
foreign import ccall "new_thing"
newThing :: IO Thing
foreign import ccall "new_subthing"
newSubthing :: Thing -> IO Subthing
-----snap-----
I can't do, as I would like:
-----snip-----
foreign import ccall "del_thing"
delThing :: Thing -> IO ()
foreign import ccall "del_subthing"
delSubthing :: Subthing -> IO ()
main =
do
p1 <- newThing
p2 <- newSubthing p1
fp1 <- newForeignPtr delThing p1
fp2 <- newForeignPtr (\p -> delSubthing p >> touchForeignPtr fp1) p2
{- ...do more funny things... -}
-----snap-----
So because touchForeignPtr is a Haskell function, I must go through a
wrapper. It seems strange to me that the Haskell storage manager would
not be able to call Haskell routines as finalizers directly...
Assuming that's really the only way to do it, I suppose my code would
look like this, correct?
-----snip-----
foreign import ccall "&del_thing"
delThing_p :: FunPtr (Thing -> IO ())
foreign import ccall "del_subthing"
delSubthing :: Subthing -> IO ()
foreign import ccall "wrapper"
mkFinPtr :: (Ptr () -> IO ()) -> FunPtr (Ptr () -> IO ())
main =
p1 <- new_thing
p2 <- new_subthing p1
fp1 <- newForeignPtr delThing_p p1
f <- mkFinPtr (\p -> delSubthing p >> touchForeignPtr fp1)
fp2 <- newForeignPtr f p2
{- ...do the funky chicken... -}
-----snap-----
Thanks in advance,
Sven Moritz
PS: You're still great!
PPS: Do you mind being called fifi? ;-)
More information about the FFI
mailing list