File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 11import weakref
22
33# http://python.org/sf/1377858
4+ # Fixed for new-style classes in 2.5c1.
45
56ref = None
67
78def test_weakref_in_del ():
8- class Target (object ):
9+ class Target ():
910 def __del__ (self ):
1011 global ref
1112 ref = weakref .ref (self )
Original file line number Diff line number Diff line change 66
77from test import test_support
88
9+ # Used in ReferencesTestCase.test_ref_created_during_del() .
10+ ref_from_del = None
911
1012class C :
1113 def method (self ):
@@ -630,6 +632,18 @@ def callback(*args):
630632 finally :
631633 gc .set_threshold (* thresholds )
632634
635+ def test_ref_created_during_del (self ):
636+ # Bug #1377858
637+ # A weakref created in an object's __del__() would crash the
638+ # interpreter when the weakref was cleaned up since it would refer to
639+ # non-existent memory. This test should not segfault the interpreter.
640+ class Target (object ):
641+ def __del__ (self ):
642+ global ref_from_del
643+ ref_from_del = weakref .ref (self )
644+
645+ w = Target ()
646+
633647
634648class SubclassableWeakrefTestCase (unittest .TestCase ):
635649
Original file line number Diff line number Diff line change @@ -12,6 +12,10 @@ What's New in Python 2.6 alpha 1?
1212Core and builtins
1313-----------------
1414
15+ - Bug #1377858: Fix the segfaulting of the interpreter when an object created
16+ a weakref on itself during a __del__ call for new-style classes (classic
17+ classes still have the bug).
18+
1519- Bug #1579370: Make PyTraceBack_Here use the current thread, not the
1620 frame's thread state.
1721
Original file line number Diff line number Diff line change @@ -666,6 +666,17 @@ subtype_dealloc(PyObject *self)
666666 goto endlabel ; /* resurrected */
667667 else
668668 _PyObject_GC_UNTRACK (self );
669+ /* New weakrefs could be created during the finalizer call.
670+ If this occurs, clear them out without calling their
671+ finalizers since they might rely on part of the object
672+ being finalized that has already been destroyed. */
673+ if (type -> tp_weaklistoffset && !base -> tp_weaklistoffset ) {
674+ /* Modeled after GET_WEAKREFS_LISTPTR() */
675+ PyWeakReference * * list = (PyWeakReference * * ) \
676+ PyObject_GET_WEAKREFS_LISTPTR (self );
677+ while (* list )
678+ _PyWeakref_ClearRef (* list );
679+ }
669680 }
670681
671682 /* Clear slots up to the nearest base with a different tp_dealloc */
Original file line number Diff line number Diff line change @@ -57,6 +57,9 @@ clear_weakref(PyWeakReference *self)
5757 PyWeakref_GET_OBJECT (self ));
5858
5959 if (* list == self )
60+ /* If 'self' is the end of the list (and thus self->wr_next == NULL)
61+ then the weakref list itself (and thus the value of *list) will
62+ end up being set to NULL. */
6063 * list = self -> wr_next ;
6164 self -> wr_object = Py_None ;
6265 if (self -> wr_prev != NULL )
You can’t perform that action at this time.
0 commit comments