Fix crasher for when an object's __del__ creates a new weakref to itself.

Patch only fixes new-style classes; classic classes still buggy.

Closes bug #1377858.  Already backported.
This commit is contained in:
Brett Cannon 2007-01-23 23:21:22 +00:00
parent 6c5c502b91
commit f5bee30e30
5 changed files with 34 additions and 1 deletions

View File

@ -1,11 +1,12 @@
import weakref
# http://python.org/sf/1377858
# Fixed for new-style classes in 2.5c1.
ref = None
def test_weakref_in_del():
class Target(object):
class Target():
def __del__(self):
global ref
ref = weakref.ref(self)

View File

@ -6,6 +6,8 @@ import weakref
from test import test_support
# Used in ReferencesTestCase.test_ref_created_during_del() .
ref_from_del = None
class C:
def method(self):
@ -630,6 +632,18 @@ class ReferencesTestCase(TestBase):
finally:
gc.set_threshold(*thresholds)
def test_ref_created_during_del(self):
# Bug #1377858
# A weakref created in an object's __del__() would crash the
# interpreter when the weakref was cleaned up since it would refer to
# non-existent memory. This test should not segfault the interpreter.
class Target(object):
def __del__(self):
global ref_from_del
ref_from_del = weakref.ref(self)
w = Target()
class SubclassableWeakrefTestCase(unittest.TestCase):

View File

@ -12,6 +12,10 @@ What's New in Python 2.6 alpha 1?
Core and builtins
-----------------
- Bug #1377858: Fix the segfaulting of the interpreter when an object created
a weakref on itself during a __del__ call for new-style classes (classic
classes still have the bug).
- Bug #1579370: Make PyTraceBack_Here use the current thread, not the
frame's thread state.

View File

@ -666,6 +666,17 @@ subtype_dealloc(PyObject *self)
goto endlabel; /* resurrected */
else
_PyObject_GC_UNTRACK(self);
/* New weakrefs could be created during the finalizer call.
If this occurs, clear them out without calling their
finalizers since they might rely on part of the object
being finalized that has already been destroyed. */
if (type->tp_weaklistoffset && !base->tp_weaklistoffset) {
/* Modeled after GET_WEAKREFS_LISTPTR() */
PyWeakReference **list = (PyWeakReference **) \
PyObject_GET_WEAKREFS_LISTPTR(self);
while (*list)
_PyWeakref_ClearRef(*list);
}
}
/* Clear slots up to the nearest base with a different tp_dealloc */

View File

@ -57,6 +57,9 @@ clear_weakref(PyWeakReference *self)
PyWeakref_GET_OBJECT(self));
if (*list == self)
/* If 'self' is the end of the list (and thus self->wr_next == NULL)
then the weakref list itself (and thus the value of *list) will
end up being set to NULL. */
*list = self->wr_next;
self->wr_object = Py_None;
if (self->wr_prev != NULL)