This looks fairly delicate and might have consequences for debuggers (which tend to keep things on the stack around after a proper tailcalling implementation (or whatever) would have dumped it). It seems like your example could be handled by calling the free function in the Haskell code that invokes the C code that invokes the callback: foreign import enumThingies :: Thingies -> (FunPtr (Thingy -> IO ())) -> IO () printThingies xs = do cb <- makeCB (\ x -> printThingy xs x) -- <- the callback enumThingies xs cb -- <- the C function freeHaskellFunPtr cb How much worse would it be to write your code in this way? I'd prefer not to commit all future implementations to working a particular way unless there's a compelling need. -- Alastair Sven:
Just for clarification: Is it OK to call freeHaskellFunPtr in the Haskell function pointed to itself, i.e. a kind of "self destruction"? Example:
foreign import ccall "wrapper" makeCB :: IO () -> IO (FunPtr (IO ()))
... funPtr <- mfix (\self -> makeCB (do freeHaskellFunPtr self; ...)) <register funPtr somewhere in C land> ...
The FFI spec doesn't say anything about this, but it would be very handy if this was allowed, e.g. for one-shot callbacks. After a short look into GHC's and Hugs' RTS I think it is OK for both systems: The thunk/adjustor has always a jump at its end, so free-ing the machine code at the jump destination does no harm.