[Gtk-sharp-list] refcounting, GC, and glade.. (patch, need review)
Vladimir Vukicevic
vladimir@pobox.com
Sun, 13 Oct 2002 04:05:34 -0700 (PDT)
(Continuing this riveting discussion ;)
I implemented a GLib.GType class with enough stuff to at least let you
navigate the GType hierarchy and get at least names of classes and the
like. I also added some debugging info in GLib.Object:DisposeNative.
Given this, upon application Quit (or any other time when a GC
occurs during runtime), I have:
XML:~XML Handle: 0x836b940
Object:DisposeNative ptr: 0x836b940 gtype: GladeXML csobj: 0x8066700 cstype: XML
XML:~XML Handle: 0x836b940
Object:DisposeNative ptr: 0x836b940 gtype: csobj: 0x80664c0 cstype: XML
(Mphoto:4066): GLib-GObject-CRITICAL **: file gobject.c: line 1307 (g_object_unref): assertion `G_IS_OBJECT (object)' failed
So I've got two different Glade.XML objects that ended up with he same
Handle, without a Ref. (the csobj pointers are different.)
There seem to be a number of other instances of this same problem; I
just seem to be running into a fairly easily repeatable case of this.
Object:DisposeNative ptr: 0x84269d0 gtype: GtkTextBuffer csobj: 0x8632500 cstype: TextBuffer
Object:DisposeNative ptr: 0x84269d0 gtype: GtkTextBuffer csobj: 0x86297e0 cstype: TextBuffer
Object:DisposeNative ptr: 0x84269d0 gtype: csobj: 0x8629780 cstype: TextBuffer
(Mphoto:4076): GLib-GObject-CRITICAL **: file gobject.c: line 1307 (g_object_unref): assertion `G_IS_OBJECT (object)' failed
Object:DisposeNative ptr: 0x84269d0 gtype: csobj: 0x8619ba0 cstype: TextBuffer
(Mphoto:4076): GLib-GObject-CRITICAL **: file gobject.c: line 1307 (g_object_unref): assertion `G_IS_OBJECT (object)' failed
(lots more of these)
These bugs are all pretty much the case of multiple C# objects being
instantiated with the same underlying Handle. With a whole lot of
copious debug output, I ended up with:
Index: glib/Object.cs
===================================================================
RCS file: /cvs/public/gtk-sharp/glib/Object.cs,v
retrieving revision 1.29
diff -u -w -u -r1.29 Object.cs
--- glib/Object.cs 12 Sep 2002 19:21:46 -0000 1.29
+++ glib/Object.cs 13 Oct 2002 10:56:58 -0000
@@ -105,8 +105,11 @@
public static Object GetObject(IntPtr o)
{
Object obj = (Object)Objects[(int)o];
- if (obj != null) return obj;
- return GtkSharp.ObjectManager.CreateObject(o);
+ if (obj == null) {
+ obj = GtkSharp.ObjectManager.CreateObject(o);
+ Objects[(int)o] = obj;
+ }
+ return obj;
}
/// <summary>
Note that nowhere else was the object actually getting cached
(i.e. the hashtable was always empty).
This "fixes" all of my problems, but i'm not sure it's correct. I
don't understand gtk ref semantics well enough; I considered something
like this:
public static Object GetObject(IntPtr o)
{
Object obj = (Object)Objects[(int)o];
if (obj == null) {
obj = GtkSharp.ObjectManager.CreateObject(o);
Objects[(int)o] = obj;
} else {
g_object_unref (o);
}
return obj;
}
But that didn't go over so well. The whole idea seems to be that you
want a 1-1 mapping between a GObject* and its C# GLib.Object -- this
means that you only want to keep one gobject "ref" on the C# side, and
let the garbage collector & friends deal with keeping track of the
GLib.Object instance. Perhaps instead of unref'ing everything but the
first, we should just ref the first... but at this point i'm just
making stabs in the dark.
- Vlad