summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorPeter Bierma <zintensitydev@gmail.com>2024-12-16 19:31:44 (GMT)
committerGitHub <noreply@github.com>2024-12-16 19:31:44 (GMT)
commit3b766824fe59030100964752be0556084d4461af (patch)
tree5986d46e9e7a744bb6581b218539f60168ff6ef6 /Lib/test
parent4937ba54c0ff7cc4a83d7345d398b804365af2d6 (diff)
downloadcpython-3b766824fe59030100964752be0556084d4461af.zip
cpython-3b766824fe59030100964752be0556084d4461af.tar.gz
cpython-3b766824fe59030100964752be0556084d4461af.tar.bz2
gh-126907: make `atexit` thread safe in free-threading (#127935)
Co-authored-by: Victor Stinner <vstinner@python.org> Co-authored-by: Kumar Aditya <kumaraditya@python.org>
Diffstat (limited to 'Lib/test')
-rw-r--r--Lib/test/test_atexit.py35
1 files changed, 34 insertions, 1 deletions
diff --git a/Lib/test/test_atexit.py b/Lib/test/test_atexit.py
index 913b755..eb01da6 100644
--- a/Lib/test/test_atexit.py
+++ b/Lib/test/test_atexit.py
@@ -4,7 +4,7 @@ import textwrap
import unittest
from test import support
from test.support import script_helper
-
+from test.support import threading_helper
class GeneralTest(unittest.TestCase):
def test_general(self):
@@ -46,6 +46,39 @@ class FunctionalTest(unittest.TestCase):
self.assertEqual(res.out.decode().splitlines(), ["atexit2", "atexit1"])
self.assertFalse(res.err)
+ @threading_helper.requires_working_threading()
+ @support.requires_resource("cpu")
+ @unittest.skipUnless(support.Py_GIL_DISABLED, "only meaningful without the GIL")
+ def test_atexit_thread_safety(self):
+ # GH-126907: atexit was not thread safe on the free-threaded build
+ source = """
+ from threading import Thread
+
+ def dummy():
+ pass
+
+
+ def thready():
+ for _ in range(100):
+ atexit.register(dummy)
+ atexit._clear()
+ atexit.register(dummy)
+ atexit.unregister(dummy)
+ atexit._run_exitfuncs()
+
+
+ threads = [Thread(target=thready) for _ in range(10)]
+ for thread in threads:
+ thread.start()
+
+ for thread in threads:
+ thread.join()
+ """
+
+ # atexit._clear() has some evil side effects, and we don't
+ # want them to affect the rest of the tests.
+ script_helper.assert_python_ok("-c", textwrap.dedent(source))
+
@support.cpython_only
class SubinterpreterTest(unittest.TestCase):