cpython: c1d0df056c19 (original) (raw)
Mercurial > cpython
changeset 104273:c1d0df056c19
merge 3.6 (#26617) [#26617]
Benjamin Peterson benjamin@python.org | |
---|---|
date | Tue, 04 Oct 2016 00:00:35 -0700 |
parents | 8c005be54305(current diff)520cb70ecb90(diff) |
children | 3fed30fa37f4 |
files | Misc/NEWS |
diffstat | 3 files changed, 24 insertions(+), 13 deletions(-)[+] [-] Lib/test/test_weakref.py 8 Misc/NEWS 2 Objects/typeobject.c 27 |
line wrap: on
line diff
--- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -845,6 +845,14 @@ class ReferencesTestCase(TestBase): with self.assertRaises(AttributeError): ref1.callback = lambda ref: None
- def test_callback_gcs(self):
class ObjectWithDel(Object):[](#l1.8)
def __del__(self): pass[](#l1.9)
x = ObjectWithDel(1)[](#l1.10)
ref1 = weakref.ref(x, lambda ref: support.gc_collect())[](#l1.11)
del x[](#l1.12)
support.gc_collect()[](#l1.13)
+ class SubclassableWeakrefTestCase(TestBase):
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ What's New in Python 3.7.0 alpha 1 Core and Builtins ----------------- +- Issue #26617: Fix crash when GC runs during weakref callbacks. +
- Issue #27942: String constants now interned recursively in tuples and frozensets.
- Issue #28289: ImportError.init now resets not specified attributes.
--- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1136,11 +1136,6 @@ subtype_dealloc(PyObject *self) Py_TRASHCAN_SAFE_BEGIN(self); --_PyTrash_delete_nesting; -- tstate->trash_delete_nesting;
- /* DO NOT restore GC tracking at this point. weakref callbacks
* (if any, and whether directly here or indirectly in something we[](#l3.8)
* call) may trigger GC, and if self is tracked at that point, it[](#l3.9)
* will look like trash to GC and GC will try to delete self again.[](#l3.10)
*/[](#l3.11)
/* Find the nearest base with a different tp_dealloc */ base = type; @@ -1151,30 +1146,36 @@ subtype_dealloc(PyObject *self) has_finalizer = type->tp_finalize || type->tp_del;
- if (type->tp_finalize) { if (PyObject_CallFinalizerFromDealloc(self) < 0) { /* Resurrected */ goto endlabel; }
- }
- /* If we added a weaklist, we clear it. Do this before calling
tp_del, clearing slots, or clearing the instance dict. */[](#l3.31)
_PyObject_GC_UNTRACK(self);[](#l3.32)
- }
- /*
If we added a weaklist, we clear it. Do this *before* calling tp_del,[](#l3.35)
clearing slots, or clearing the instance dict.[](#l3.36)
GC tracking must be off at this point. weakref callbacks (if any, and[](#l3.38)
whether directly here or indirectly in something we call) may trigger GC,[](#l3.39)
and if self is tracked at that point, it will look like trash to GC and GC[](#l3.40)
will try to delete self again.[](#l3.41)
- */ if (type->tp_weaklistoffset && !base->tp_weaklistoffset) PyObject_ClearWeakRefs(self);
_PyObject_GC_TRACK(self);[](#l3.47) type->tp_del(self);[](#l3.48) if (self->ob_refcnt > 0) {[](#l3.49) /* Resurrected */[](#l3.50) goto endlabel;[](#l3.51) }[](#l3.52)
} if (has_finalizer) {_PyObject_GC_UNTRACK(self);[](#l3.53)
_PyObject_GC_UNTRACK(self);[](#l3.56) /* New weakrefs could be created during the finalizer call.[](#l3.57) If this occurs, clear them out without calling their[](#l3.58) finalizers since they might rely on part of the object[](#l3.59)