Finalizers: the Legend that Won't Die

George Russell ger at
Thu Feb 27 14:45:24 EST 2003

I geve the example

> let
>    x = seq (unsafePerformIO runFinalizers) y
>    finalizer = [... something involving x ...]
> [... attach finalizer to something ..]
> [... something becomes free, putting finalizer on the to-be-done list ...]
> [.., computation requiring x ...]

to which Malcolm replied (snipped)

 > But isn't this just the same as any other program that contains a
 > blackhole fault?  i.e. the program is logically incorrect.
No I don't think it is logically incorrect.  There's nothing terribly
illogical about the user thinking in the middle of a long pure computation
"Let's free up some space by running the finalizers".  Nor indeed is there
anything illogical about unsafePerformIO'ing some other operation which
indirectly involves running finalizers.  (You
might logically do this at the end of some call to an pure-function-like
external function, where you need to construct some complex data structure
requiring finalizers, and think it would be a good idea to run the finalizers
immediately afterwards.)

Of course the example I gave is an extremely artificial one, but I see no reason
why similar but much more complicated cases should not arise in "real life".

 > What is more, the runtime system will probably tell you "Blackhole detected!"
 > or "<<loop>>" or something, which is helpful.
Well I suppose it's more helpful than hitting you over the head with a blunt
instrument but it's not *very* helpful is it?  You see "<<loop>>".  The first
reaction would be to assume you have a normal circularity.  After a few happy
minutes, or hours, discovering that this is not the case, you might work out
that finalizers are somehow responsible, at which point you have to detect an
arbitrarily complex cycle involving finalizers and partially-evaluated values.
To make this more fun, you are relying on various unspecified properties of the
garbage-collector and whatever external programs you are calling, meaning that it's
very possible the bug will only occur sporadically, depending on the amount of memory
the Haskell process is able to malloc or whatever.

More information about the FFI mailing list