]> granicus.if.org Git - python/commitdiff
Fix a subtle bug in the trashcan code I added yesterday to
authorGuido van Rossum <guido@python.org>
Wed, 7 Aug 2002 20:42:09 +0000 (20:42 +0000)
committerGuido van Rossum <guido@python.org>
Wed, 7 Aug 2002 20:42:09 +0000 (20:42 +0000)
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.

Objects/typeobject.c

index b7edb143b9254a8d12512afa9b1ae8e3a24464be..d49434448ab6996839f4c0c3abc73b6c6a083b52 100644 (file)
@@ -463,13 +463,13 @@ subtype_dealloc(PyObject *self)
        /* We get here only if the type has GC */
 
        /* UnTrack and re-Track around the trashcan macro, alas */
-       _PyObject_GC_UNTRACK(self);
+       PyObject_GC_UnTrack(self);
        Py_TRASHCAN_SAFE_BEGIN(self);
        _PyObject_GC_TRACK(self); /* We'll untrack for real later */
 
        /* Maybe call finalizer; exit early if resurrected */
        if (call_finalizer(self) < 0)
-               return;
+               goto endlabel;
 
        /* Find the nearest base with a different tp_dealloc
           and clear slots while we're at it */
@@ -508,6 +508,7 @@ subtype_dealloc(PyObject *self)
        /* Can't reference self beyond this point */
        Py_DECREF(type);
 
+  endlabel:
        Py_TRASHCAN_SAFE_END(self);
 }