[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: scheme closures: crash during garbage collection
From: |
Andy Wingo |
Subject: |
Re: scheme closures: crash during garbage collection |
Date: |
Mon, 19 Jun 2006 11:53:53 +0200 |
Hi Gregory,
Nice analysis. My brain hasn't fully processed it yet, as it just got to
mye today -- I had to go poking in my spam folder for it :-/
> I propose the following alternative strategy, which does not cause the
> fatal error:
>
> - When creating a gclosure from a scheme procedure, instead of calling
> scm_gc_protect_object() on the scheme procedure, add the scheme
> procedure to a 'master list' of all scheme procedures being used
> in this way.
> - Ensure that all such procedures on the master list are protected
> from scheme's garbage collector. This is easily accomplished by
> making sure that scheme has a reference to the master list itself
> and that the master list, when it is marked, also marks all of its
> members.
> - When a gclosure is finalized, instead of calling
> scm_gc_unprotect_object() on the scheme function, add the function
> to a "defunct list" of scheme procedures that no longer need
> protection.
> - At some convenient time, say from a glib idle function, remove all
> items on the "defunct list" from the "master list"; next time
> scheme's
> garbage collector runs, it can free the scheme functions that are
> no longer being used as callbacks.
Initial reactions:
- using the glib loop is really distasteful -- you have no guarantee
that the program will use the loop
- python has this solved, afaict -- we should see what they do
- mark functions are likely the correct implementation strategy, so
that we can detect ref cycles without destroy()
Also, consider glib/REFCOUNTING:
1. A closure connected to a GObject signal should not be collected until
either the closure is disconnected, or the object itself (not the
wrapper) goes out of existence.
2. Attaching closures to an object should not prevent the object from being
freed. Otherwise, any object with a connected signal will live forever.
Closures should only have a weak reference on an object.
These specifications are mutually exclusive. Stipulation 2 means that a
closure cannot be a permanent object, because its environment will always
reference the wrapper. But for it to be invoked after the wrapper is
collected would mean that its environment would have to be valid, which would
always include the wrapper object. So, either the closure must be invalidated
and collected when the object is collected (violating stipulation 1), or the
object must be immortal as long as it has signals connected to it (violating
stipulation 2).
Since it is a common idiom to find an object, connect to it, and then forget
about it, we will choose to violate stipulation 2. However, when
%gtype-instance-primitive-destroy! is called on a GTypeInstance, we
invalidate all guile closures.
Just some thoughts. I don't fully understand the problem yet, other than
the fact that we seem to be working against guile's gc atm.
Regards,
--
Andy Wingo
http://wingolog.org/