From 7a98ffe7fac84cf34fb75f0507ff15b08f763471 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 16 Mar 2024 12:55:46 +0100 Subject: [PATCH] gh-112536: Add test_threading to TSAN tests (#116898) --- Lib/test/libregrtest/tsan.py | 1 + Lib/test/support/script_helper.py | 4 ++-- Lib/test/test_threading.py | 24 ++++++++++++++++-------- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Lib/test/libregrtest/tsan.py b/Lib/test/libregrtest/tsan.py index 150fcec8816179e..fde8ba937c0e4b7 100644 --- a/Lib/test/libregrtest/tsan.py +++ b/Lib/test/libregrtest/tsan.py @@ -14,6 +14,7 @@ 'test_syslog', 'test_thread', 'test_threadedtempfile', + 'test_threading', 'test_threading_local', 'test_threadsignals', ] diff --git a/Lib/test/support/script_helper.py b/Lib/test/support/script_helper.py index 759020c33aa7000..65e0bc199e7f0b5 100644 --- a/Lib/test/support/script_helper.py +++ b/Lib/test/support/script_helper.py @@ -63,8 +63,8 @@ class _PythonRunResult(collections.namedtuple("_PythonRunResult", """Helper for reporting Python subprocess run results""" def fail(self, cmd_line): """Provide helpful details about failed subcommand runs""" - # Limit to 80 lines to ASCII characters - maxlen = 80 * 100 + # Limit to 300 lines of ASCII characters + maxlen = 300 * 100 out, err = self.out, self.err if len(out) > maxlen: out = b'(... truncated stdout ...)' + out[-maxlen:] diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 9769cb41e3e689d..886866626dc9f84 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -47,14 +47,11 @@ def skip_unless_reliable_fork(test): return unittest.skip("due to known OS bug related to thread+fork")(test) if support.HAVE_ASAN_FORK_BUG: return unittest.skip("libasan has a pthread_create() dead lock related to thread+fork")(test) + if support.check_sanitizer(thread=True): + return unittest.skip("TSAN doesn't support threads after fork") return test -skip_if_tsan_fork = unittest.skipIf( - support.check_sanitizer(thread=True), - "TSAN doesn't support threads after fork") - - def requires_subinterpreters(meth): """Decorator to skip a test if subinterpreters are not supported.""" return unittest.skipIf(interpreters is None, @@ -428,6 +425,10 @@ def test_finalize_running_thread(self): # Issue 1402: the PyGILState_Ensure / _Release functions may be called # very late on python exit: on deallocation of a running thread for # example. + if support.check_sanitizer(thread=True): + # the thread running `time.sleep(100)` below will still be alive + # at process exit + self.skipTest("TSAN would report thread leak") import_module("ctypes") rc, out, err = assert_python_failure("-c", """if 1: @@ -460,6 +461,11 @@ def waitingThread(): def test_finalize_with_trace(self): # Issue1733757 # Avoid a deadlock when sys.settrace steps into threading._shutdown + if support.check_sanitizer(thread=True): + # the thread running `time.sleep(2)` below will still be alive + # at process exit + self.skipTest("TSAN would report thread leak") + assert_python_ok("-c", """if 1: import sys, threading @@ -639,7 +645,6 @@ def test_daemon_param(self): self.assertTrue(t.daemon) @skip_unless_reliable_fork - @skip_if_tsan_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. @@ -709,7 +714,6 @@ def f(): @skip_unless_reliable_fork @unittest.skipUnless(hasattr(os, 'waitpid'), "test needs os.waitpid()") - @skip_if_tsan_fork def test_main_thread_after_fork(self): code = """if 1: import os, threading @@ -1278,7 +1282,6 @@ def test_2_join_in_forked_process(self): self._run_and_join(script) @skip_unless_reliable_fork - @skip_if_tsan_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. @@ -1311,6 +1314,11 @@ def test_4_daemon_threads(self): # Check that a daemon thread cannot crash the interpreter on shutdown # by manipulating internal structures that are being disposed of in # the main thread. + if support.check_sanitizer(thread=True): + # some of the threads running `random_io` below will still be alive + # at process exit + self.skipTest("TSAN would report thread leak") + script = """if True: import os import random