[Python-checkins] cpython (merge 3.5 -> 3.5): Merge heads

serhiy.storchaka python-checkins at python.org
Tue Oct 4 11:25:17 EDT 2016


https://hg.python.org/cpython/rev/b674fd340a23
changeset: 104279:b674fd340a23
branch: 3.5
parent: 104276:d7ab3241aef2
parent: 104271:c9b7272e2553
user: Serhiy Storchaka <storchaka at gmail.com>
date: Tue Oct 04 18:23:55 2016 +0300
summary:
 Merge heads
files:
 Lib/test/test_weakref.py | 8 ++++++++
 Misc/NEWS | 2 ++
 Objects/typeobject.c | 27 ++++++++++++++-------------
 3 files changed, 24 insertions(+), 13 deletions(-)
diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -845,6 +845,14 @@
 with self.assertRaises(AttributeError):
 ref1.__callback__ = lambda ref: None
 
+ def test_callback_gcs(self):
+ class ObjectWithDel(Object):
+ def __del__(self): pass
+ x = ObjectWithDel(1)
+ ref1 = weakref.ref(x, lambda ref: support.gc_collect())
+ del x
+ support.gc_collect()
+
 
 class SubclassableWeakrefTestCase(TestBase):
 
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,8 @@
 
 - Issue #28350: String constants with null character no longer interned.
 
+- Issue #26617: Fix crash when GC runs during weakref callbacks.
+
 - Issue #27942: String constants now interned recursively in tuples and frozensets.
 
 - Issue #21578: Fixed misleading error message when ImportError called with
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -1123,11 +1123,6 @@
 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
- * call) may trigger GC, and if self is tracked at that point, it
- * will look like trash to GC and GC will try to delete self again.
- */
 
 /* Find the nearest base with a different tp_dealloc */
 base = type;
@@ -1138,30 +1133,36 @@
 
 has_finalizer = type->tp_finalize || type->tp_del;
 
- /* Maybe call finalizer; exit early if resurrected */
- if (has_finalizer)
+ if (type->tp_finalize) {
 _PyObject_GC_TRACK(self);
-
- 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. */
+ _PyObject_GC_UNTRACK(self);
+ }
+ /*
+ If we added a weaklist, we clear it. Do this *before* calling tp_del,
+ clearing slots, or clearing the instance dict.
+
+ GC tracking must be off at this point. weakref callbacks (if any, and
+ whether directly here or indirectly in something we call) may trigger GC,
+ and if self is tracked at that point, it will look like trash to GC and GC
+ will try to delete self again.
+ */
 if (type->tp_weaklistoffset && !base->tp_weaklistoffset)
 PyObject_ClearWeakRefs(self);
 
 if (type->tp_del) {
+ _PyObject_GC_TRACK(self);
 type->tp_del(self);
 if (self->ob_refcnt > 0) {
 /* Resurrected */
 goto endlabel;
 }
+ _PyObject_GC_UNTRACK(self);
 }
 if (has_finalizer) {
- _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
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /