summaryrefslogtreecommitdiff
path: root/gi/pygobject-object.c
diff options
context:
space:
mode:
authorChristoph Reiter <creiter@src.gnome.org>2017-10-26 17:24:02 +0200
committerChristoph Reiter <creiter@src.gnome.org>2017-10-26 17:40:19 +0200
commit5f63b8c626eb7f27de346dac2b66f07794e61b07 (patch)
tree89ef0420fb39f5654806aa4f35f62db7092285f6 /gi/pygobject-object.c
parentf13b0d6e0d97e21aa2a4553a036362dec9d0c4cb (diff)
downloadgobject-introspection-5f63b8c626eb7f27de346dac2b66f07794e61b07.tar.gz
pygobject-object: Fix Python GC collecting a ref cycle too early
PyGObject traverses its closures in tp_traverse, but the lifetime of the closures is tied to the lifetime of the GObject and not the wrapper. This confuses the Python GC when it sees a ref cycle and tries to break it up with tp_clear. Since tp_clear will not invalidate the closure and only invalidate the Python wrapper the closure callback gets called with the now cleared/invalid object. Instead let the GC only check the Python objects referenced by the closure when tp_clear would actually free them and as a result break the cycle. This is only the case when the wrapped object would be freed by tp_clear which is when its reference count is at 1. Original patch by Gustavo Carneiro: https://bugzilla.gnome.org/show_bug.cgi?id=546802#c5 https://bugzilla.gnome.org/show_bug.cgi?id=731501
Diffstat (limited to 'gi/pygobject-object.c')
-rw-r--r--gi/pygobject-object.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/gi/pygobject-object.c b/gi/pygobject-object.c
index ca82ffb9..729bb4dc 100644
--- a/gi/pygobject-object.c
+++ b/gi/pygobject-object.c
@@ -1168,8 +1168,10 @@ pygobject_traverse(PyGObject *self, visitproc visit, void *arg)
if (self->inst_dict) ret = visit(self->inst_dict, arg);
if (ret != 0) return ret;
- if (data) {
-
+ /* Only let the GC track the closures when tp_clear() would free them.
+ * https://bugzilla.gnome.org/show_bug.cgi?id=731501
+ */
+ if (data && self->obj->ref_count == 1) {
for (tmp = data->closures; tmp != NULL; tmp = tmp->next) {
PyGClosure *closure = tmp->data;