GNOME Bugzilla – Bug 127909
Reference counting of BonoboObject-derived types is broken
Last modified: 2004-12-22 21:47:04 UTC
The example program I'll attach ilustrates the problem. My theory on what is happening follows. A BonoboObject contains two reference counters: 1. the GObject reference count; 2. the Bonobo::Unknown reference count. When a BonoboObject is created, both counters are initialized to 1. When the bonobo reference count drops to zero, the 'destroy' signal is fired, and after that the GObject reference count is decremented. The reason for this is that you may want to keep a floating GObject reference, and then let the (remote) CORBA client manage the lifecycle of the object. When the last unref happens, bonobo unrefs the GObject so that it is destroyed. Unfortunately, gnome-python is treating BonoboObject like any ordinary GObject, which it is not. With BonoboObject, the caller owns the bonobo reference count, but not the GObject reference count. Based on this, I see two possible solutions: 1. add an extra reference to the GObject in the constructor of BonoboObject-derived classes, or 2. keep only a weak link to the GObject.
Created attachment 21804 [details] example program demonstrating problem
Been looking through the Bonobo code to get a feel for what the lifecycle for an individual BonoboObject and the aggregate behave in a C program. It is something like this: 1) When a BonoboObject gets created, a BonoboAggregateObject gets created with aggregate refcount 1. The GObject reference count is incremented to give a refcount of 2. 2) bonobo_object_add_interface() has the effect of merging the BonoboAggregateObjects for each BonoboObject into one (it essentially joins the BonoboObject lists in the aggregate and fixes up the refcounts). 3) bonobo_object_ref() increments the BonoboObject's aggregate's refcount. 4) on bonobo_object_unref(), the aggregate refcount gets decremented. If the refcount would hit zero, then bonobo_object_destroy_T() gets called first. This goes through the BonoboObject list for the aggregate and emits the "destroy" signal on each one then decrements it's GObject reference count. If the aggregate doesn't get resurrected by the destructors, bonobo_object_finalize_internal_T() gets called which removes the BonoboObjects from the aggregate's object list, deactivates the servants and decrements the GObject reference count a second time. Some key point is that when you create a BonoboObject, you own the single aggregate reference count, while the aggregate owns the two GObject references on the actual BonoboObject. How do things differ for Python? We assume that when you construct an object, you would own the GObject reference to it. This means that if the aggregate gets finalised before the Python wrapper for the BonoboObject does, it will find that the BonoboObject has already hit refcount==0 (similar will happen for the other order). The closest we come to this situation in PyGTK is GtkWindows -- when you create a GtkWindow with gtk_window_new(), you don't actually own the initial reference. Things are special cased to g_object_ref() GtkWindows on construction to work around this. We could probably do the same for BonoboObjects. Does this sound like it might be the cause of the problem?
Just so this details aren't lost. The 2 GObject references are: 1- the implicit reference created by the constructor; 2- An additional ref added in bonobo_object_constructor The g_object_unref's are in: bonobo_object_finalize_internal_T bonobo_object_finalize_servant And I think you have indeed spotted the problem. PyGTK does not own the GObject reference owned by BonoboObject constructors, so we need to add an additional g_object_ref in the python constructors.
Created attachment 22105 [details] [review] codegen fix to honor the caller-owns-return flag in constructors
Created attachment 22107 [details] [review] example of usage of new codegen feature in bonobo
Created attachment 22108 [details] slightly changed test program
The extra g_object_ref takes care of problem completely. :-)
Created attachment 22118 [details] [review] full patch to fix all bonobo constructors
Created attachment 22592 [details] [review] new codegen patch, a longer but more correct one.
Committed both codegen and gnome-python parts. Bug should be fixed.