[Python-Dev] Re: GC and ExtensionClass - a summary of the problem and a workaround

James Henstridge james@daa.com.au
Thu, 17 May 2001 15:18:23 +0800 (WST)


On Thu, 17 May 2001 skip@pobox.com wrote:

>
> Over the past couple days I've included python-dev on various messages in an
> ongoing thread about a segmentation violation I was getting with the new
> PyGtk2 wrappers.  With some excellent assistance from the GC maestro, Neil
> Schemenauer, I finally know what's going on and I have a simple workaround
> that lets me get back to work.  Here's a summary of the problem.
>
> When defining ExtensionClass types, you need to create and initialize a
> PyExtensionClass struct.  It looks something like so:
>
>     PyExtensionClass PyGtkTreeSortable_Type = {
> 	PyObject_HEAD_INIT(NULL)
> 	0,				/* ob_size */
> 	"GtkTreeSortable",			/* tp_name */
> 	sizeof(PyPureMixinObject),	/* tp_basicsize */
> 	...
>     };
>
> Note that the parameter to the PyObject_HEAD_INIT macro is NULL.  It would
> normally be the address of a type object (e.g. &PyType_Type).  However, Jim
> Fulton pointed out that on Windows you can't get the address of &PyType_Type
> object at compile time.  Accordingly, ExtensionClass provides a
> PyExtensionClass_Export macro whose responsibility is, in part, to set the
> ob_type field appropriately at runtime.  (I'm not sure why this Windows nit
> doesn't afflict other type declarations like PyTuple_Type.  I'm sure others
> will know why.  I just accept Jim's word as gospel and move on...)

Well, for Extension Classes, PyType_Type is not correct either.  And
because ExtensionClass is loaded at runtime, we can't set the ob_type
field in the initialiser even on Unix systems.

>
> A problem arises if the garbage collector runs while the module
> initialization function is running, but before all the ob_type fields have
> been assigned their correct values.  In this case, a one-element tuple
> representing the bases of a particular PyGtk extension class was traversed
> by the garbage collector.
>
> The workaround turns out to be exceedingly simple:
>
>     import gc
>     gc.disable()
>     import gtk
>     gc.enable()
>
> I can handle doing that from Python code for the time being and will leave
> it up to others to decide how, if at all, ExtensionClass should be changed
> to correct the problem.

Thanks for debugging this problem Skip.  If we don't find a correct
solution to the problem, I can put the gc disable/enable calls inside the
gtk/__init__.py module.

James.