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.
This commit is contained in:
parent
b3b9ade4a3
commit
0c2b509f9d
|
@ -753,6 +753,26 @@ class CPythonOrderedDictTests(OrderedDictTests, unittest.TestCase):
|
|||
self.assertEqual(list(unpickled), expected)
|
||||
self.assertEqual(list(it), expected)
|
||||
|
||||
@support.cpython_only
|
||||
def test_weakref_list_is_not_traversed(self):
|
||||
# Check that the weakref list is not traversed when collecting
|
||||
# OrderedDict objects. See bpo-39778 for more information.
|
||||
|
||||
gc.collect()
|
||||
|
||||
x = self.OrderedDict()
|
||||
x.cycle = x
|
||||
|
||||
cycle = []
|
||||
cycle.append(cycle)
|
||||
|
||||
x_ref = weakref.ref(x)
|
||||
cycle.append(x_ref)
|
||||
|
||||
del x, cycle, x_ref
|
||||
|
||||
gc.collect()
|
||||
|
||||
|
||||
class PurePythonOrderedDictSubclassTests(PurePythonOrderedDictTests):
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Fixed a crash due to incorrect handling of weak references in
|
||||
``collections.OrderedDict`` classes. Patch by Pablo Galindo.
|
|
@ -1454,7 +1454,6 @@ odict_traverse(PyODictObject *od, visitproc visit, void *arg)
|
|||
_ODictNode *node;
|
||||
|
||||
Py_VISIT(od->od_inst_dict);
|
||||
Py_VISIT(od->od_weakreflist);
|
||||
_odict_FOREACH(od, node) {
|
||||
Py_VISIT(_odictnode_KEY(node));
|
||||
}
|
||||
|
@ -1467,7 +1466,6 @@ static int
|
|||
odict_tp_clear(PyODictObject *od)
|
||||
{
|
||||
Py_CLEAR(od->od_inst_dict);
|
||||
Py_CLEAR(od->od_weakreflist);
|
||||
PyDict_Clear((PyObject *)od);
|
||||
_odict_clear_nodes(od);
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue