Author: Armin Rigo <[email protected]>
Branch: py3.5
Changeset: r88496:e7e2aa356442
Date: 2016-11-20 17:26 +0100
http://bitbucket.org/pypy/pypy/changeset/e7e2aa356442/
Log: Test and fix for frame.clear()
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -782,8 +782,10 @@
def descr_clear(self, space):
"""F.clear(): clear most references held by the frame"""
- # Clears a random subset of the attributes (e.g. the fast
- # locals, but not f_locals).
+ # Clears a random subset of the attributes: the local variables
+ # and the w_locals. Note that CPython doesn't clear f_locals
+ # (which can create leaks) but it's hard to notice because
+ # the next Python-level read of 'frame.f_locals' will clear it.
if not self.frame_finished_execution:
if not self._is_generator_or_coroutine():
raise oefmt(space.w_RuntimeError,
@@ -800,6 +802,8 @@
debug = self.getdebug()
if debug is not None:
debug.w_f_trace = None
+ if debug.w_locals is not None:
+ debug.w_locals = space.newdict()
# clear the locals, including the cell/free vars, and the stack
for i in range(len(self.locals_cells_stack_w)):
diff --git a/pypy/interpreter/test/test_pyframe.py
b/pypy/interpreter/test/test_pyframe.py
--- a/pypy/interpreter/test/test_pyframe.py
+++ b/pypy/interpreter/test/test_pyframe.py
@@ -618,6 +618,15 @@
#
raises(StopIteration, next, gen)
+ def test_frame_clear_really(self):
+ import sys
+ def f(x):
+ return sys._getframe()
+ frame = f(42)
+ assert frame.f_locals['x'] == 42
+ frame.clear()
+ assert frame.f_locals == {}
+
def test_throw_trace_bug(self):
import sys
def f():
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit