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(unpickled), expected)
|
||||||
self.assertEqual(list(it), 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):
|
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;
|
_ODictNode *node;
|
||||||
|
|
||||||
Py_VISIT(od->od_inst_dict);
|
Py_VISIT(od->od_inst_dict);
|
||||||
Py_VISIT(od->od_weakreflist);
|
|
||||||
_odict_FOREACH(od, node) {
|
_odict_FOREACH(od, node) {
|
||||||
Py_VISIT(_odictnode_KEY(node));
|
Py_VISIT(_odictnode_KEY(node));
|
||||||
}
|
}
|
||||||
|
@ -1467,7 +1466,6 @@ static int
|
||||||
odict_tp_clear(PyODictObject *od)
|
odict_tp_clear(PyODictObject *od)
|
||||||
{
|
{
|
||||||
Py_CLEAR(od->od_inst_dict);
|
Py_CLEAR(od->od_inst_dict);
|
||||||
Py_CLEAR(od->od_weakreflist);
|
|
||||||
PyDict_Clear((PyObject *)od);
|
PyDict_Clear((PyObject *)od);
|
||||||
_odict_clear_nodes(od);
|
_odict_clear_nodes(od);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue