[Patches] Trashcan vs. GC vs. TRACE_REFS

Charles G Waldman cgw@fnal.gov
Tue, 25 Apr 2000 14:17:26 -0500


Hi Christian et al.

Well, I said there was nothing wrong with Trashcan, but I spoke a
little too soon ;-)

With the current gc-cycle patch and Py_TRACE_REFS set, we get a core
dump.

The culprit is this little piece of code in object.c

void
_Py_Dealloc(op)
	PyObject *op;
{
	destructor dealloc = op->ob_type->tp_dealloc;
	_Py_ForgetReference(op);
***	if (_PyTrash_delete_nesting < PyTrash_UNWIND_LEVEL-1)
***	    op->ob_type = NULL; 
	(*dealloc)(op);
}


I'd really love to understand what those lines marked "***" are for.

If you set ob_type to NULL before doing a dealloc, you get into
trouble, because the new GC dealloc functions need to check ob_type to
decide if the object being deleted has GC info.  By setting type to
NULL you are breaking this.

But what really seems odd to me is that the _Py_Dealloc function above
is only used when Py_TRACE_REFS is set.  Normally the following macro
definition is used instead (see object.h)

ifndef Py_TRACE_REFS
...
#define _Py_Dealloc(op) (*(op)->ob_type->tp_dealloc)((PyObject *)(op))
...
#endif /* !Py_TRACE_REFS */

So, what is the point of worrying about _PyTrash_UNWIND_LEVEL only in
a function which is only used in special builds?  If this is really
important, I'd think you'd be doing it in the _Py_Dealloc macro as
well.  But, of course, you can't be clobbering ob_type at all, because
the gc dealloc functions *need* that ob_type.

As far as I can tell, building with Py_TRACE_REFS is not too widely
done.  But I'm finding it incredibly useful for tracking down those
reference leaks which still remain even with Neil's GC patches in
place.