summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_gc.py
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2021-05-21 22:50:11 (GMT)
committerGitHub <noreply@github.com>2021-05-21 22:50:11 (GMT)
commit50b0d148a68072292832eb69bdf1815b8059355f (patch)
treefa1d73efadcf398b0c6dd33b364e13841d66b8a0 /Lib/test/test_gc.py
parent856958d0e750a62bd5e6a231c3ed67aa0db32e11 (diff)
downloadcpython-50b0d148a68072292832eb69bdf1815b8059355f.zip
cpython-50b0d148a68072292832eb69bdf1815b8059355f.tar.gz
cpython-50b0d148a68072292832eb69bdf1815b8059355f.tar.bz2
bpo-44184: Fix subtype_dealloc() for freed type (GH-26274) (GH-26290)
Fix a crash at Python exit when a deallocator function removes the last strong reference to a heap type. Don't read type memory after calling basedealloc() since basedealloc() can deallocate the type and free its memory. _PyMem_IsPtrFreed() argument is now constant. (cherry picked from commit 615069eb08494d089bf24e43547fbc482ed699b8) Co-authored-by: Victor Stinner <vstinner@python.org> Co-authored-by: Victor Stinner <vstinner@python.org>
Diffstat (limited to 'Lib/test/test_gc.py')
-rw-r--r--Lib/test/test_gc.py34
1 files changed, 33 insertions, 1 deletions
diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py
index ee4fe49..1528cf6 100644
--- a/Lib/test/test_gc.py
+++ b/Lib/test/test_gc.py
@@ -1361,6 +1361,34 @@ class GCTogglingTests(unittest.TestCase):
# empty __dict__.
self.assertEqual(x, None)
+
+class PythonFinalizationTests(unittest.TestCase):
+ def test_ast_fini(self):
+ # bpo-44184: Regression test for subtype_dealloc() when deallocating
+ # an AST instance also destroy its AST type: subtype_dealloc() must
+ # not access the type memory after deallocating the instance, since
+ # the type memory can be freed as well. The test is also related to
+ # _PyAST_Fini() which clears references to AST types.
+ code = textwrap.dedent("""
+ import ast
+ import codecs
+
+ # Small AST tree to keep their AST types alive
+ tree = ast.parse("def f(x, y): return 2*x-y")
+ x = [tree]
+ x.append(x)
+
+ # Put the cycle somewhere to survive until the last GC collection.
+ # Codec search functions are only cleared at the end of
+ # interpreter_clear().
+ def search_func(encoding):
+ return None
+ search_func.a = x
+ codecs.register(search_func)
+ """)
+ assert_python_ok("-c", code)
+
+
def test_main():
enabled = gc.isenabled()
gc.disable()
@@ -1370,7 +1398,11 @@ def test_main():
try:
gc.collect() # Delete 2nd generation garbage
- run_unittest(GCTests, GCTogglingTests, GCCallbackTests)
+ run_unittest(
+ GCTests,
+ GCCallbackTests,
+ GCTogglingTests,
+ PythonFinalizationTests)
finally:
gc.set_debug(debug)
# test gc.enable() even if GC is disabled by default