Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 34fae03

Browse filesBrowse files
serhiy-storchakalarryhastings
authored andcommitted
[3.4] bpo-26617: Ensure gc tracking is off when invoking weakref callbacks. (#2695)
* [3.4] bpo-26617: Ensure gc tracking is off when invoking weakref callbacks. (cherry picked from commit 8f657c3) * Rewrite a NEWS entry as a NEWS.d entry.
1 parent 6f6bc1d commit 34fae03
Copy full SHA for 34fae03

File tree

Expand file treeCollapse file tree

3 files changed

+22
-12
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+22
-12
lines changed

‎Lib/test/test_weakref.py

Copy file name to clipboardExpand all lines: Lib/test/test_weakref.py
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,14 @@ def test_set_callback_attribute(self):
827827
with self.assertRaises(AttributeError):
828828
ref1.__callback__ = lambda ref: None
829829

830+
def test_callback_gcs(self):
831+
class ObjectWithDel(Object):
832+
def __del__(self): pass
833+
x = ObjectWithDel(1)
834+
ref1 = weakref.ref(x, lambda ref: support.gc_collect())
835+
del x
836+
support.gc_collect()
837+
830838

831839
class SubclassableWeakrefTestCase(TestBase):
832840

+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix crash when GC runs during weakref callbacks.

‎Objects/typeobject.c

Copy file name to clipboardExpand all lines: Objects/typeobject.c
+13-12Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,11 +1116,6 @@ subtype_dealloc(PyObject *self)
11161116
Py_TRASHCAN_SAFE_BEGIN(self);
11171117
--_PyTrash_delete_nesting;
11181118
-- tstate->trash_delete_nesting;
1119-
/* DO NOT restore GC tracking at this point. weakref callbacks
1120-
* (if any, and whether directly here or indirectly in something we
1121-
* call) may trigger GC, and if self is tracked at that point, it
1122-
* will look like trash to GC and GC will try to delete self again.
1123-
*/
11241119

11251120
/* Find the nearest base with a different tp_dealloc */
11261121
base = type;
@@ -1131,30 +1126,36 @@ subtype_dealloc(PyObject *self)
11311126

11321127
has_finalizer = type->tp_finalize || type->tp_del;
11331128

1134-
/* Maybe call finalizer; exit early if resurrected */
1135-
if (has_finalizer)
1136-
_PyObject_GC_TRACK(self);
1137-
11381129
if (type->tp_finalize) {
1130+
_PyObject_GC_TRACK(self);
11391131
if (PyObject_CallFinalizerFromDealloc(self) < 0) {
11401132
/* Resurrected */
11411133
goto endlabel;
11421134
}
1135+
_PyObject_GC_UNTRACK(self);
11431136
}
1144-
/* If we added a weaklist, we clear it. Do this *before* calling
1145-
tp_del, clearing slots, or clearing the instance dict. */
1137+
/*
1138+
If we added a weaklist, we clear it. Do this *before* calling tp_del,
1139+
clearing slots, or clearing the instance dict.
1140+
1141+
GC tracking must be off at this point. weakref callbacks (if any, and
1142+
whether directly here or indirectly in something we call) may trigger GC,
1143+
and if self is tracked at that point, it will look like trash to GC and GC
1144+
will try to delete self again.
1145+
*/
11461146
if (type->tp_weaklistoffset && !base->tp_weaklistoffset)
11471147
PyObject_ClearWeakRefs(self);
11481148

11491149
if (type->tp_del) {
1150+
_PyObject_GC_TRACK(self);
11501151
type->tp_del(self);
11511152
if (self->ob_refcnt > 0) {
11521153
/* Resurrected */
11531154
goto endlabel;
11541155
}
1156+
_PyObject_GC_UNTRACK(self);
11551157
}
11561158
if (has_finalizer) {
1157-
_PyObject_GC_UNTRACK(self);
11581159
/* New weakrefs could be created during the finalizer call.
11591160
If this occurs, clear them out without calling their
11601161
finalizers since they might rely on part of the object

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.