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