Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0c2b509

Browse files
authored
bpo-39778: Don't traverse weak-reference lists OrderedDict's tp_traverse and tp_clear (GH-18749)
Objects do not own weak references to them directly through the __weakref__ list so these do not need to be traversed by the GC.
1 parent b3b9ade commit 0c2b509

3 files changed

Lines changed: 22 additions & 2 deletions

File tree

Lib/test/test_ordered_dict.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,26 @@ def test_iterators_pickling(self):
753753
self.assertEqual(list(unpickled), expected)
754754
self.assertEqual(list(it), expected)
755755

756+
@support.cpython_only
757+
def test_weakref_list_is_not_traversed(self):
758+
# Check that the weakref list is not traversed when collecting
759+
# OrderedDict objects. See bpo-39778 for more information.
760+
761+
gc.collect()
762+
763+
x = self.OrderedDict()
764+
x.cycle = x
765+
766+
cycle = []
767+
cycle.append(cycle)
768+
769+
x_ref = weakref.ref(x)
770+
cycle.append(x_ref)
771+
772+
del x, cycle, x_ref
773+
774+
gc.collect()
775+
756776

757777
class PurePythonOrderedDictSubclassTests(PurePythonOrderedDictTests):
758778

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed a crash due to incorrect handling of weak references in
2+
``collections.OrderedDict`` classes. Patch by Pablo Galindo.

Objects/odictobject.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,7 +1454,6 @@ odict_traverse(PyODictObject *od, visitproc visit, void *arg)
14541454
_ODictNode *node;
14551455

14561456
Py_VISIT(od->od_inst_dict);
1457-
Py_VISIT(od->od_weakreflist);
14581457
_odict_FOREACH(od, node) {
14591458
Py_VISIT(_odictnode_KEY(node));
14601459
}
@@ -1467,7 +1466,6 @@ static int
14671466
odict_tp_clear(PyODictObject *od)
14681467
{
14691468
Py_CLEAR(od->od_inst_dict);
1470-
Py_CLEAR(od->od_weakreflist);
14711469
PyDict_Clear((PyObject *)od);
14721470
_odict_clear_nodes(od);
14731471
return 0;

0 commit comments

Comments
 (0)