[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.

Andy Wingo

reply via email to

[Prev in Thread] Current Thread [Next in Thread]