Bug in touchForeignPtr?

Benjamin Franksen benjamin.franksen at bessy.de
Mon Nov 22 12:27:57 EST 2004


On Monday 22 November 2004 14:45, Simon Marlow wrote:
> On 20 November 2004 23:02, Benjamin Franksen wrote:
> > I am using Foreign.Concurrent.newForeignPtr and touchForeignPtr
> > inside the finalizers to express liveness dependencies as hinted to
> > by the documentation. This doesn't seem to work, though, or at least
> > I can't see what I've done wrong. I attached a test module; compiled
> > with ghc -fglasgow-exts --make TestForeignTouchBug.hs, ghc version
> > 6.2.2, this gives
> >
> > .../foreigntouchbug > ./a.out
> > <hit enter here>
> > before finalizing A
> > after finalizing A
> > before finalizing B
> > after finalizing B
> > <hit enter here>
> >
> > I expected the order of the finalizer calls be be the other way
> > around, since the finalizer for the Bs explicitly touches the A value.
>
> The problem is that the runtime is running all outstanding finalizers at
> the end of execution, without regard for GC dependencies like the ones
> introduced by touchForeignPtr.

I understand that there are situations where finalizers cannot be guaranteed 
to run: First because of an unconditional termination signal (SIGKILL), 
second because of circular dependencies resulting in a deadlock.

I don't understand why it is necessary to "performGC" explicitly, in order to 
run finalizers at *normal* program termination and without a deadlock.

BTW, the sensible thing to do in this case would be to throw an exception 
whenever a deadlock condition is detected. (That is, if it can be detected.)

However, what I don't understand is why touchForeignPtr is not honored in my 
example program: Note that the output text lines from the finalizers appear 
*before* the last action in the program (which is a second getChar). The 
finalizers *are* called by the GC, and still the order is wrong.

> I've been planning to remove this automatic running of finalizers for
> other reasons.   However, then you will get absolutely no guarantee that
> your finalizer will ever run at all (indeed, the property isn't always
> true right now, but it is usually true).

It is unclear to me what "usually" means, here. Wouldn't it be better to state 
the conditions under which they are called resp. aren't?

Documenting the current state of affairs would be to say

- Finalizers are *not* guaranteed to run (instead they "usually" are, whatever 
that means).

- Calling touchForeignPtr does *not* guarantee that the targeted foreignPtr is 
not finalized before this call.

This would make it obvious that finalizers are not a reliable tool (which they 
aren't, at the moment).

> Let me share with you something that I've come to appreciate over the
> last few years:
>
>   Finalizers are almost always not the right thing.
>
> Finalizers look terribly attractive, but often lead to a huge can of
> worms - best avoided if at all possible.

I am ready to believe this, but I am nevertheless somewhat disturbed.

I use finalizers to automatically reclaim resources from a foreign library. If 
I don't use them, these resources must be reclaimed explicitly. This is bad 
for two reasons:

(1) The programmer has to remember to reclaim resources.
(2) Handles for such resources become invalid after reclamation.

If finalizers are not the right thing, what else is?

Ben
-- 
Top level things with identity are evil.	-- Lennart Augustsson


More information about the Glasgow-haskell-users mailing list