[Python-checkins] cpython (merge 3.5 -> default): Issue #25935: Garbage collector now breaks reference loops with OrderedDict.
serhiy.storchaka
python-checkins at python.org
Tue Jan 19 07:49:13 EST 2016
https://hg.python.org/cpython/rev/5f0a08cfc4f6
changeset: 99986:5f0a08cfc4f6
parent: 99984:f2586c381b0b
parent: 99985:627575e9a7aa
user: Serhiy Storchaka <storchaka at gmail.com>
date: Tue Jan 19 14:48:42 2016 +0200
summary:
Issue #25935: Garbage collector now breaks reference loops with OrderedDict.
files:
Lib/test/test_ordered_dict.py | 13 +++++++++++
Misc/NEWS | 2 +
Objects/odictobject.c | 27 +++++++++++-----------
3 files changed, 29 insertions(+), 13 deletions(-)
diff --git a/Lib/test/test_ordered_dict.py b/Lib/test/test_ordered_dict.py
--- a/Lib/test/test_ordered_dict.py
+++ b/Lib/test/test_ordered_dict.py
@@ -1,10 +1,12 @@
import contextlib
import copy
+import gc
import pickle
from random import randrange, shuffle
import struct
import sys
import unittest
+import weakref
from collections.abc import MutableMapping
from test import mapping_tests, support
@@ -593,6 +595,17 @@
dict.update(od, [('spam', 1)])
self.assertNotIn('NULL', repr(od))
+ def test_reference_loop(self):
+ # Issue 25935
+ OrderedDict = self.OrderedDict
+ class A:
+ od = OrderedDict()
+ A.od[A] = None
+ r = weakref.ref(A)
+ del A
+ gc.collect()
+ self.assertIsNone(r())
+
class PurePythonOrderedDictTests(OrderedDictTests, unittest.TestCase):
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -133,6 +133,8 @@
Library
-------
+- Issue #25935: Garbage collector now breaks reference loops with OrderedDict.
+
- Issue #16620: Fixed AttributeError in msilib.Directory.glob().
- Issue #26013: Added compatibility with broken protocol 2 pickles created
diff --git a/Objects/odictobject.c b/Objects/odictobject.c
--- a/Objects/odictobject.c
+++ b/Objects/odictobject.c
@@ -772,19 +772,17 @@
{
_ODictNode *node, *next;
- if (!_odict_EMPTY(od)) {
- node = _odict_FIRST(od);
- while (node != NULL) {
- next = _odictnode_NEXT(node);
- _odictnode_DEALLOC(node);
- node = next;
- }
- _odict_FIRST(od) = NULL;
- _odict_LAST(od) = NULL;
- }
-
_odict_free_fast_nodes(od);
od->od_fast_nodes = NULL;
+
+ node = _odict_FIRST(od);
+ _odict_FIRST(od) = NULL;
+ _odict_LAST(od) = NULL;
+ while (node != NULL) {
+ next = _odictnode_NEXT(node);
+ _odictnode_DEALLOC(node);
+ node = next;
+ }
}
/* There isn't any memory management of nodes past this point. */
@@ -1233,8 +1231,6 @@
{
PyDict_Clear((PyObject *)od);
_odict_clear_nodes(od);
- _odict_FIRST(od) = NULL;
- _odict_LAST(od) = NULL;
if (_odict_resize(od) < 0)
return NULL;
Py_RETURN_NONE;
@@ -1556,8 +1552,13 @@
static int
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));
+ }
return PyDict_Type.tp_traverse((PyObject *)od, visit, arg);
}
--
Repository URL: https://hg.python.org/cpython
More information about the Python-checkins
mailing list