GNOME Bugzilla – Bug 640868
Wrong gobject refcount when calling introspected constructors for widgets
Last modified: 2013-02-03 21:40:27 UTC
Here is an example below. >>> l = Gtk.Button.new() >>> l.__grefcount__ 2 >>> l = Gtk.Button() >>> l.__grefcount__ 1 The __grefcount__ should be the same in both cases. I think the issue is that Gtk.Button.new() returns an object with a floating reference, which is reffed by pygobject (so that makes 2 refs, despite the object is not owned by anyone). We should probably use ref_sink() instead for objects returned with transfer full. The reference count is correct for Gtk.Window.new() (which has a "sunk floating ref", transfer none) and for GdkPixbuf.Pixbuf.new() (which return a regular ref, transfer full)
I made a mistake in the above comment: gtk_button_new() is actually (transfer none) because there are 'zero refs' on it when it's returned.
Created attachment 179559 [details] [review] Fix wrong refcount when calling introspected widget constructors Introspected widget constructors, like Gtk.Button.new(), can return objects with a floating reference, which was then reffed by pygobject, resulting in two references, despite the object is not owned by anyone. This patch uses ref_sink() when pygobject takes its own reference, to avoid adding that extra reference. Hence we now claim ownership on objects returned by constructors with transfer=none (which is the case for nearly all the widget constructors, despite the floating ref).
Created attachment 179876 [details] [review] Fix wrong refcount when calling introspected widget constructors Added a test case. Without the patch, the new test case failed with this error: ====================================================================== FAIL: test_floating (test_everything.TestEverything) ---------------------------------------------------------------------- Traceback (most recent call last):
+ Trace 225814
self.assertEquals(e.__grefcount__, 1) AssertionError: 2 != 1
Review of attachment 179876 [details] [review]: This one is great, thanks!
After this change, this now crashes: from gi.repository import Gtk, GObject class Thing(Gtk.HBox): pass GObject.new(Thing)
It works if you do Thing() instead. That makes me think the issue is this: - the object is created (refcount 1, floating) - __init__ is called: the wrapper is created, and takes ownership (refcount 1) - __init__ is finished, and the wrapper is discarded (refcount 0) - g_object_new returns, and a new wrapper is created for an object which was already finalized. So we need to somehow figure out this wrapper is created within a constructor, and not sink the ref in this case specifically. I suppose the previous patch might be reverted in the meantime to avoid such crashes and have leaks instead.
This patch was committed over a year ago, closing. Thanks!