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

M.-A. Lemburg mal@lemburg.com
Thu, 17 May 2001 08:54:37 +0200


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...)
> 
> 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.

I wonder how the GC collector could "see" the type object before
it has been initialized... since PyGtkTreeSortable_Type is a static
C array and not a known PyObject until you add it to some Python
dictionary as type object or use it for creating instances, it
seems strange that the GC collector can reach out for it and
get hit by the fact that it is not yet properly initialized.

Some logic in PyExtensionClass_Export() or the GTK module must
be twisted.
 
> 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.

-- 
Marc-Andre Lemburg
______________________________________________________________________
Company & Consulting:                           http://www.egenix.com/
Python Software:                        http://www.lemburg.com/python/