From: yihong Date: Wed, 15 Oct 2025 15:25:06 +0000 (+0800) Subject: [3.14] gh-140080: Add test for executing `atexit` callbacks under no memory (GH-140161) X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5caf64335cb3504d0b1321b9da6ef1a0a040eb43;p=thirdparty%2FPython%2Fcpython.git [3.14] gh-140080: Add test for executing `atexit` callbacks under no memory (GH-140161) --- diff --git a/Lib/test/test_atexit.py b/Lib/test/test_atexit.py index eb01da6e88a8..30c445a9c2a5 100644 --- a/Lib/test/test_atexit.py +++ b/Lib/test/test_atexit.py @@ -1,9 +1,11 @@ import atexit import os +import subprocess import textwrap import unittest +from test.support import os_helper from test import support -from test.support import script_helper +from test.support import SuppressCrashReport, script_helper from test.support import threading_helper class GeneralTest(unittest.TestCase): @@ -133,6 +135,37 @@ class SubinterpreterTest(unittest.TestCase): self.assertEqual(os.read(r, len(expected)), expected) os.close(r) + # Python built with Py_TRACE_REFS fail with a fatal error in + # _PyRefchain_Trace() on memory allocation error. + @unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build') + def test_atexit_with_low_memory(self): + # gh-140080: Test that setting low memory after registering an atexit + # callback doesn't cause an infinite loop during finalization. + code = textwrap.dedent(""" + import atexit + import _testcapi + + def callback(): + print("hello") + + atexit.register(callback) + # Simulate low memory condition + _testcapi.set_nomemory(0) + """) + + with os_helper.temp_dir() as temp_dir: + script = script_helper.make_script(temp_dir, 'test_atexit_script', code) + with SuppressCrashReport(): + with script_helper.spawn_python(script, + stderr=subprocess.PIPE) as proc: + proc.wait() + stdout = proc.stdout.read() + stderr = proc.stderr.read() + + self.assertIn(proc.returncode, (0, 1)) + self.assertNotIn(b"hello", stdout) + self.assertIn(b"MemoryError", stderr) + if __name__ == "__main__": unittest.main()