After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 71435 - cyclic garbage collection and signal handlers
cyclic garbage collection and signal handlers
Status: RESOLVED FIXED
Product: gnome-python
Classification: Deprecated
Component: general
1.99.x
Other All
: Normal minor
: ---
Assigned To: James Henstridge
James Henstridge
Depends on:
Blocks: 71021
 
 
Reported: 2002-02-14 02:21 UTC by James Henstridge
Modified: 2004-12-22 21:47 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Makes signals collectable by the Python garbage collector (21.59 KB, patch)
2002-07-08 11:49 UTC, Arjan J. Molenaar
none Details | Review
Python app demonstrating the gcable-signals patch (8.61 KB, patch)
2002-07-08 11:54 UTC, Arjan J. Molenaar
none Details | Review

Description James Henstridge 2002-02-14 02:21:51 UTC
when you connect a signal handler, a couple of python objects are wrapped
up in a GClosure.  This closure is then connected as a handler for the signal.

Effectively, those object references in the closure are owned by the
wrapper PyObject for the GObject.

We can easily get cyclic references by passing object pointers as data for
the signals:
  a.connect('foo', b)
  b.connect('bar', a)

Python has the facility to break these loops with its cyclic garbage
collection features.  It would be nice to get pygtk to hook into this.

It would essentially involve keeping a list of the closures associated with
the object, so we can traverse them in the tp_traverse slot, and be able to
disconnect them in the tp_clear slot.  Cleaning up references in the list
when signals get removed could be done with a finalise notify in the
closure itself.
Comment 1 Arjan J. Molenaar 2002-07-05 12:20:21 UTC
I've been looking into this signalling stuff, since it would be very
nice for Gaphor to have it working.

The owner of the signal should own the closure right?

IMHO a GList should be added to PyGObject, where we can add closures.
pyg_closure_new() should have an extra parameter: the (to be) owner of
the closure. This will allow pyg_closure_destroy() to remove itself
from the owning PyGObject.

Maybe even better: create an extra method pyg_object_add_closure(self,
callback, args, swap_data) that can be used as a wrapper around
pyg_closure_new(). Here we can add an extra finalize_notifier that
removes the closure from the list. PyGObject should still have an
extra attribute, though. This will avoid vague dependencies. 
PyGClosure will have its own traverse method.

The same thing has to be done for set_(q)data()...
Comment 2 Arjan J. Molenaar 2002-07-08 11:49:07 UTC
Created attachment 9706 [details] [review]
Makes signals collectable by the Python garbage collector
Comment 3 Arjan J. Molenaar 2002-07-08 11:52:32 UTC
About the patch: It adds a new field to PyGObject: closures. When
gobject_traverse() or pygobjet_clear() or *_dealloc() is called the
closure list is also visited. Closures are now made via
pygobject_closure_new() which has an extra (first) argument: self, the
owner of the closure. I've patched gtk.override and libglade.override
too. 
Comment 4 Arjan J. Molenaar 2002-07-08 11:54:22 UTC
Created attachment 9707 [details] [review]
Python app demonstrating the gcable-signals patch
Comment 5 James Henstridge 2002-07-09 15:35:45 UTC
Thank you for the patch.  I have applied a reworked version of the
patch.  I added a pygobject_watch_closure() API instead of
pygobject_closure_new().

Also, I moved the cleanup handler for PyGClosure into an invalidate
handler rather than finalise.  When watching a closure, we add an
invalidate notifier that unwatches the closure.  For the tp_clear()
slot of the GObject wrapper, we simply invalidate all the watched
closures (which unwatches it for us, and decrefs the PyObjects that
the closure references).

This seems to be a better way of doing things (after reading some more
of the glib code).  Your unit test for the signal code passes with my
modifications to your patch.