diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2013-08-01 18:56:12 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2013-08-01 18:56:12 (GMT) |
commit | 2d350fd8af29eada0c3f264a91df6ab4af4a05fd (patch) | |
tree | 4c3a89ff8841950525e764e69c5e51d93aa04b78 /Lib/test/test_atexit.py | |
parent | 7a2572cb4987c5dad3e478e40086e038b701a163 (diff) | |
download | cpython-2d350fd8af29eada0c3f264a91df6ab4af4a05fd.zip cpython-2d350fd8af29eada0c3f264a91df6ab4af4a05fd.tar.gz cpython-2d350fd8af29eada0c3f264a91df6ab4af4a05fd.tar.bz2 |
Issue #18619: Fix atexit leaking callbacks registered from sub-interpreters, and make it GC-aware.
Diffstat (limited to 'Lib/test/test_atexit.py')
-rw-r--r-- | Lib/test/test_atexit.py | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/Lib/test/test_atexit.py b/Lib/test/test_atexit.py index 5200af7..3e25236 100644 --- a/Lib/test/test_atexit.py +++ b/Lib/test/test_atexit.py @@ -2,6 +2,7 @@ import sys import unittest import io import atexit +import _testcapi from test import support ### helpers @@ -23,7 +24,9 @@ def raise1(): def raise2(): raise SystemError -class TestCase(unittest.TestCase): + +class GeneralTest(unittest.TestCase): + def setUp(self): self.save_stdout = sys.stdout self.save_stderr = sys.stderr @@ -122,8 +125,43 @@ class TestCase(unittest.TestCase): self.assertEqual(l, [5]) +class SubinterpreterTest(unittest.TestCase): + + def test_callbacks_leak(self): + # This test shows a leak in refleak mode if atexit doesn't + # take care to free callbacks in its per-subinterpreter module + # state. + n = atexit._ncallbacks() + code = r"""if 1: + import atexit + def f(): + pass + atexit.register(f) + del atexit + """ + ret = _testcapi.run_in_subinterp(code) + self.assertEqual(ret, 0) + self.assertEqual(atexit._ncallbacks(), n) + + def test_callbacks_leak_refcycle(self): + # Similar to the above, but with a refcycle through the atexit + # module. + n = atexit._ncallbacks() + code = r"""if 1: + import atexit + def f(): + pass + atexit.register(f) + atexit.__atexit = atexit + """ + ret = _testcapi.run_in_subinterp(code) + self.assertEqual(ret, 0) + self.assertEqual(atexit._ncallbacks(), n) + + def test_main(): - support.run_unittest(TestCase) + support.run_unittest(__name__) + if __name__ == "__main__": test_main() |