[Haskell-cafe] Re: Haskell FFI and finalizers

Maxime Henrion mux at FreeBSD.org
Tue Oct 9 11:12:19 EDT 2007

Simon Marlow wrote:
> Maxime Henrion wrote:
> >Stefan O'Rear wrote:
> >>On Thu, Oct 04, 2007 at 12:55:41AM +0200, Maxime Henrion wrote:
> >>>When writing the binding for foo_new(), I need to open a file with
> >>>fopen() to pass it the FILE *.  Then I get a struct foo * that I can
> >>>easily associate the the foo_destroy() finalizer.  However, when
> >>>finalizing the struct foo * object, I want to also close the FILE *
> >>>handle.
> >>>
> >>>If I write a small C function for doing the finalizer myself, I still
> >>>wouldn't get passed the FILE * to close, only the struct foo * pointer
> >>>which is of no use.
> >>Ah, yes, this does make the situation more interesting.
> >>
> >>Looks like newForeignPtrEnv is maybe what you want?
> >
> >Yeah, this is what I use now.  I wrote a player_finalizer() function in
> >C, that takes a FILE * and a pointer to the struct I'm handling, and
> >which just closes the file.  I then added these sources to the mix in my
> >.cabal file (with C-Sources, Extra-Includes, etc), and registered this
> >new finalizer using addForeignPtrFinalizerEnv.
> >
> >This makes me want to ask you, what is so bad about Foreign.Concurrent
> >that it should be avoided at almost any cost?  It sure is likely to be
> >much slower than just calling a plain C finalizer, but aren't Haskell
> >threads super-cheap anyways?
> In GHC ordinary ForeignPtr finalizers are implemented using 
> Foreign.Concurrent anyway.  It's not so much that Foreign.Concurrent should 
> be avoided at all costs, but rather finalizers in general should be 
> avoided, especially if you really care about when they run (i.e. bad things 
> could happen if they run late or at unpredictable times).
> The Haskell code is not run "by the garbage collector", rather the garbage 
> collector figures out which finalizers need running and creates a thread to 
> run them.  It's perfectly safe to have C finalizers that invoke Haskell 
> code using GHC, although this is explicitly undefined by the FFI spec.
> The reason that Foreign.Concurrent is separate from Foreign.ForeignPtr is 
> that it does essentially require concurrency to implement, whereas ordinary 
> C finalizers can be run by the GC (although GHC doesn't do it this way).

Thank you for those precisions, Simon.  It seems that even if using the
Foreign.Concurrent module isn't a problem per-self, I'd be better off
using a plain C finalizer that I write myself, if only for portability
with other FFI implementations.


More information about the Haskell-Cafe mailing list