summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_scope.py
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2013-05-10 15:47:42 (GMT)
committerGuido van Rossum <guido@python.org>2013-05-10 15:47:42 (GMT)
commit6832c81d5d2d730c38bab001e0c1b4b0569dd5ef (patch)
treef4725451768bda1987adf4eca22d2e232018fd9f /Lib/test/test_scope.py
parent8c01ffa6ede5da92ab144ad2ea609a96e308b1e6 (diff)
downloadcpython-6832c81d5d2d730c38bab001e0c1b4b0569dd5ef.zip
cpython-6832c81d5d2d730c38bab001e0c1b4b0569dd5ef.tar.gz
cpython-6832c81d5d2d730c38bab001e0c1b4b0569dd5ef.tar.bz2
#17927: Keep frame from referencing cell-ified arguments.
Diffstat (limited to 'Lib/test/test_scope.py')
-rw-r--r--Lib/test/test_scope.py41
1 files changed, 40 insertions, 1 deletions
diff --git a/Lib/test/test_scope.py b/Lib/test/test_scope.py
index f4ed244..1c06224 100644
--- a/Lib/test/test_scope.py
+++ b/Lib/test/test_scope.py
@@ -1,3 +1,4 @@
+import gc
import unittest
from test.support import check_syntax_error, cpython_only, run_unittest
@@ -713,7 +714,6 @@ class ScopeTests(unittest.TestCase):
def b():
global a
-
def testClassNamespaceOverridesClosure(self):
# See #17853.
x = 42
@@ -727,6 +727,45 @@ class ScopeTests(unittest.TestCase):
self.assertFalse(hasattr(X, "x"))
self.assertEqual(x, 42)
+ @cpython_only
+ def testCellLeak(self):
+ # Issue 17927.
+ #
+ # The issue was that if self was part of a cycle involving the
+ # frame of a method call, *and* the method contained a nested
+ # function referencing self, thereby forcing 'self' into a
+ # cell, setting self to None would not be enough to break the
+ # frame -- the frame had another reference to the instance,
+ # which could not be cleared by the code running in the frame
+ # (though it will be cleared when the frame is collected).
+ # Without the lambda, setting self to None is enough to break
+ # the cycle.
+ logs = []
+ class Canary:
+ def __del__(self):
+ logs.append('canary')
+ class Base:
+ def dig(self):
+ pass
+ class Tester(Base):
+ def __init__(self):
+ self.canary = Canary()
+ def dig(self):
+ if 0:
+ lambda: self
+ try:
+ 1/0
+ except Exception as exc:
+ self.exc = exc
+ super().dig()
+ self = None # Break the cycle
+ tester = Tester()
+ tester.dig()
+ del tester
+ logs.append('collect')
+ gc.collect()
+ self.assertEqual(logs, ['canary', 'collect'])
+
def test_main():
run_unittest(ScopeTests)