[Python-checkins] python/dist/src/Objects typeobject.c,2.166,2.167

gvanrossum@users.sourceforge.net gvanrossum@users.sourceforge.net
Wed, 07 Aug 2002 13:42:11 -0700


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv3424

Modified Files:
	typeobject.c 
Log Message:
Fix a subtle bug in the trashcan code I added yesterday to
subtype_dealloc().

When call_finalizer() failed, it would return without going through
the trashcan end macro, thereby unbalancing the trashcan nesting level
counter, and thereby defeating the test case (slottrash() in
test_descr.py).  This in turn meant that the assert in the GC_UNTRACK
macro wasn't triggered by the slottrash() test despite a bug in the
code: _PyTrash_destroy_chain() calls the dealloc routine with an
object that's untracked, and the assert in the GC_UNTRACK macro would
fail on this; but because of an earlier test that resurrects an
object, causing call_finalizer() to fail and the trashcan nesting
level to be unbalanced, so _PyTrash_destroy_chain() was never called.
Calling the slottrash() test in isolation *did* trigger the assert,
however.

So the fix is twofold: (1) call the GC_UnTrack() function instead of
the GC_UNTRACK macro, because the function is safe when the object is
already untracked; (2) when call_finalizer() fails, jump to a label
that exits through the trashcan end macro, keeping the trashcan
nesting balanced.


Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.166
retrieving revision 2.167
diff -C2 -d -r2.166 -r2.167
*** typeobject.c	6 Aug 2002 21:41:44 -0000	2.166
--- typeobject.c	7 Aug 2002 20:42:09 -0000	2.167
***************
*** 464,468 ****
  
  	/* UnTrack and re-Track around the trashcan macro, alas */
! 	_PyObject_GC_UNTRACK(self);
  	Py_TRASHCAN_SAFE_BEGIN(self);
  	_PyObject_GC_TRACK(self); /* We'll untrack for real later */
--- 464,468 ----
  
  	/* UnTrack and re-Track around the trashcan macro, alas */
! 	PyObject_GC_UnTrack(self);
  	Py_TRASHCAN_SAFE_BEGIN(self);
  	_PyObject_GC_TRACK(self); /* We'll untrack for real later */
***************
*** 470,474 ****
  	/* Maybe call finalizer; exit early if resurrected */
  	if (call_finalizer(self) < 0)
! 		return;
  
  	/* Find the nearest base with a different tp_dealloc
--- 470,474 ----
  	/* Maybe call finalizer; exit early if resurrected */
  	if (call_finalizer(self) < 0)
! 		goto endlabel;
  
  	/* Find the nearest base with a different tp_dealloc
***************
*** 509,512 ****
--- 509,513 ----
  	Py_DECREF(type);
  
+   endlabel:
  	Py_TRASHCAN_SAFE_END(self);
  }