Author: Armin Rigo <[email protected]>
Branch: extradoc
Changeset: r5750:b6cd4ef2e6cc
Date: 2016-11-20 17:16 +0100
http://bitbucket.org/pypy/extradoc/changeset/b6cd4ef2e6cc/
Log: Another CPython 3.5 failure
diff --git a/planning/py3.5/cpython-crashers.rst
b/planning/py3.5/cpython-crashers.rst
--- a/planning/py3.5/cpython-crashers.rst
+++ b/planning/py3.5/cpython-crashers.rst
@@ -144,3 +144,38 @@
except IndexError:
assert next(gen) is 1
assert next(gen) is 2 # <==
+
+* frame.clear() does not clear f_locals, unlike what a test says
+ (Lib/test/test_frame.py)::
+
+ def test_locals_clear_locals(self):
+ # Test f_locals before and after clear() (to exercise caching)
+ f, outer, inner = self.make_frames()
+ outer.f_locals
+ inner.f_locals
+ outer.clear()
+ inner.clear()
+ self.assertEqual(outer.f_locals, {})
+ self.assertEqual(inner.f_locals, {})
+
+ This test passes, but the C-level PyFrameObject has got a strong
+ reference to f_locals, which is only updated (to be empty) if the
+ Python code tries to read this attribute. In the normal case,
+ code that calls clear() but doesn't read f_locals afterwards will
+ still leak everything contained in the C-level f_locals field. This
+ can be shown by this failing test::
+
+ import sys
+
+ def g():
+ x = 42
+ return sys._getframe()
+
+ frame = g()
+ d = frame.f_locals
+ frame.clear()
+ print(d)
+ assert d == {} # fails! but 'assert d is frame.f_locals' passes,
+ # which shows that this dict is kept alive by
+ # 'frame'; and we've seen that it is non-empty
+ # as long as we don't read frame.f_locals.
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit