
Thanks for your reply. I'm afraid it's left me even more confused about which way to go with this :-(
If it's possible that future Haskell FFI's don't guarantee that all finalisers are run then this more or less rules out the use of the reference counting solution (which wasn't particularly attractive anyway because it needs to be done in C AFAICS :-). If users who want this behaviour are required to code it themselves, it seems to require that they maintain a global list of all allocated ForeignPtrs. But doing that naively will stop them being garbage collected at all, unless it's possible to do something clever using weak pointers. Perhaps it is possible (or maybe some tricks at the C level could be used) but I think it's a significant extra burden for FFI users.
Yes, it would have to be a global list of weak pointers to ForeignPtrs. This topic has come up before, though not on this list. See this message, and the rest of the thread: http://www.haskell.org/pipermail/cvs-ghc/2003-January/016651.html the thread also moved on to ffi@haskell.org: http://www.haskell.org/pipermail/ffi/2003-January/001041.html and be sure to check out the paper by Hans Boehm referenced in that message, it's a good summary of the issues involved.
Also, while we're talking about this, maybe the semantics of performGC should be clarified. Does it block until all GC (and finalisation of garbage ForeignPtrs) is complete? I would guess this was the original intention, but this doesn't seem to be consistent with non-stop Haskell. If it does block, are all Haskell threads blocked, or just the calling thread?
performGC doesn't do anything that you can rely on :-) In practice, it probably starts all the finalizers that are ready to run, but it certainly doesn't wait for their termination.
Also, I could you explain what you mean by a suitable exception handler? I don't really understand this at all. I'd expected I may well end up using bracket or similar, but I'm not sure how exception handling is relevant to this problem.
Start your program something like this: import Control.Exception (finally) main = my_main `finally` clean_up my_main = ... put your program here ... clean_up = ... all the cleanup code goes here ... You can additionally use finalizers to perform incremental cleanup during program execution, but the right way to clean up at the end is to use an exception handler as above. Cheers, Simon