]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.11] gh-110031: Skip test_threading fork tests if ASAN (#110100) (#110104)
authorVictor Stinner <vstinner@python.org>
Fri, 29 Sep 2023 13:19:37 +0000 (15:19 +0200)
committerGitHub <noreply@github.com>
Fri, 29 Sep 2023 13:19:37 +0000 (15:19 +0200)
gh-110031: Skip test_threading fork tests if ASAN (#110100)

Skip test_threading tests using thread+fork if Python is built with
Address Sanitizer (ASAN).

(cherry picked from commit 86e76ab8af9a5018acbcdcbb6285678175b1bd8a)

Lib/test/test_threading.py
Misc/NEWS.d/next/Tests/2023-09-29-14-11-30.gh-issue-110031.fQnFnc.rst [new file with mode: 0644]

index b352c44a4da4db5cd3a29bdd67d624038f470a66..a4192acd6dbc5c3ceb588cacace74d70b95a008c 100644 (file)
@@ -37,6 +37,23 @@ platforms_to_skip = ('netbsd5', 'hp-ux11')
 Py_DEBUG = hasattr(sys, 'gettotalrefcount')
 
 
+# gh-89363: Skip fork() test if Python is built with Address Sanitizer (ASAN)
+# to work around a libasan race condition, dead lock in pthread_create().
+skip_if_asan_fork = support.skip_if_sanitizer(
+                        "libasan has a pthread_create() dead lock",
+                        address=True)
+
+
+def skip_unless_reliable_fork(test):
+    if not support.has_fork_support:
+        return unittest.skip("requires working os.fork()")(test)
+    if sys.platform in platforms_to_skip:
+        return unittest.skip("due to known OS bug related to thread+fork")(test)
+    if support.check_sanitizer(address=True):
+        return unittest.skip("libasan has a pthread_create() dead lock related to thread+fork")(test)
+    return test
+
+
 def restore_default_excepthook(testcase):
     testcase.addCleanup(setattr, threading, 'excepthook', threading.excepthook)
     threading.excepthook = threading.__excepthook__
@@ -533,7 +550,7 @@ class ThreadTests(BaseTestCase):
         t = threading.Thread(daemon=True)
         self.assertTrue(t.daemon)
 
-    @support.requires_fork()
+    @skip_unless_reliable_fork
     def test_fork_at_exit(self):
         # bpo-42350: Calling os.fork() after threading._shutdown() must
         # not log an error.
@@ -561,7 +578,7 @@ class ThreadTests(BaseTestCase):
         self.assertEqual(out, b'')
         self.assertEqual(err.rstrip(), b'child process ok')
 
-    @support.requires_fork()
+    @skip_unless_reliable_fork
     def test_dummy_thread_after_fork(self):
         # Issue #14308: a dummy thread in the active list doesn't mess up
         # the after-fork mechanism.
@@ -588,11 +605,7 @@ class ThreadTests(BaseTestCase):
         self.assertEqual(out, b'')
         self.assertEqual(err, b'')
 
-    @support.requires_fork()
-    # gh-89363: Skip multiprocessing tests if Python is built with ASAN to
-    # work around a libasan race condition: dead lock in pthread_create().
-    @support.skip_if_sanitizer("libasan has a pthread_create() dead lock",
-                               address=True)
+    @skip_unless_reliable_fork
     def test_is_alive_after_fork(self):
         # Try hard to trigger #18418: is_alive() could sometimes be True on
         # threads that vanished after a fork.
@@ -626,7 +639,7 @@ class ThreadTests(BaseTestCase):
         th.start()
         th.join()
 
-    @support.requires_fork()
+    @skip_unless_reliable_fork
     @unittest.skipUnless(hasattr(os, 'waitpid'), "test needs os.waitpid()")
     def test_main_thread_after_fork(self):
         code = """if 1:
@@ -647,8 +660,7 @@ class ThreadTests(BaseTestCase):
         self.assertEqual(err, b"")
         self.assertEqual(data, "MainThread\nTrue\nTrue\n")
 
-    @unittest.skipIf(sys.platform in platforms_to_skip, "due to known OS bug")
-    @support.requires_fork()
+    @skip_unless_reliable_fork
     @unittest.skipUnless(hasattr(os, 'waitpid'), "test needs os.waitpid()")
     def test_main_thread_after_fork_from_nonmain_thread(self):
         code = """if 1:
@@ -1025,8 +1037,7 @@ class ThreadJoinOnShutdown(BaseTestCase):
             """
         self._run_and_join(script)
 
-    @support.requires_fork()
-    @unittest.skipIf(sys.platform in platforms_to_skip, "due to known OS bug")
+    @skip_unless_reliable_fork
     def test_2_join_in_forked_process(self):
         # Like the test above, but from a forked interpreter
         script = """if 1:
@@ -1046,8 +1057,7 @@ class ThreadJoinOnShutdown(BaseTestCase):
             """
         self._run_and_join(script)
 
-    @support.requires_fork()
-    @unittest.skipIf(sys.platform in platforms_to_skip, "due to known OS bug")
+    @skip_unless_reliable_fork
     def test_3_join_in_forked_from_thread(self):
         # Like the test above, but fork() was called from a worker thread
         # In the forked process, the main Thread object must be marked as stopped.
@@ -1117,8 +1127,7 @@ class ThreadJoinOnShutdown(BaseTestCase):
         rc, out, err = assert_python_ok('-c', script)
         self.assertFalse(err)
 
-    @support.requires_fork()
-    @unittest.skipIf(sys.platform in platforms_to_skip, "due to known OS bug")
+    @skip_unless_reliable_fork
     def test_reinit_tls_after_fork(self):
         # Issue #13817: fork() would deadlock in a multithreaded program with
         # the ad-hoc TLS implementation.
@@ -1141,7 +1150,7 @@ class ThreadJoinOnShutdown(BaseTestCase):
         for t in threads:
             t.join()
 
-    @support.requires_fork()
+    @skip_unless_reliable_fork
     def test_clear_threads_states_after_fork(self):
         # Issue #17094: check that threads states are cleared after fork()
 
diff --git a/Misc/NEWS.d/next/Tests/2023-09-29-14-11-30.gh-issue-110031.fQnFnc.rst b/Misc/NEWS.d/next/Tests/2023-09-29-14-11-30.gh-issue-110031.fQnFnc.rst
new file mode 100644 (file)
index 0000000..a8a163c
--- /dev/null
@@ -0,0 +1,2 @@
+Skip test_threading tests using thread+fork if Python is built with Address
+Sanitizer (ASAN). Patch by Victor Stinner.