Issue #18619: Fix atexit leaking callbacks registered from sub-interpreters, and make it GC-aware.

This commit is contained in:
Antoine Pitrou 2013-08-01 20:56:12 +02:00
parent 7a2572cb49
commit 2d350fd8af
3 changed files with 122 additions and 44 deletions

View file

@ -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()