mirror of
https://github.com/python/cpython.git
synced 2025-08-15 22:30:42 +00:00
[3.12] gh-112536: Add --tsan test for reasonable TSAN execution times. (gh-116601) (#116929)
(cherry picked from commit ebf29b3
)
Co-authored-by: Donghee Na <donghee.na@python.org>
This commit is contained in:
parent
2ac1b48a04
commit
fcb230180f
8 changed files with 64 additions and 4 deletions
|
@ -164,6 +164,7 @@ class Namespace(argparse.Namespace):
|
|||
self.match_tests: TestFilter = []
|
||||
self.pgo = False
|
||||
self.pgo_extended = False
|
||||
self.tsan = False
|
||||
self.worker_json = None
|
||||
self.start = None
|
||||
self.timeout = None
|
||||
|
@ -333,6 +334,8 @@ def _create_parser():
|
|||
help='enable Profile Guided Optimization (PGO) training')
|
||||
group.add_argument('--pgo-extended', action='store_true',
|
||||
help='enable extended PGO training (slower training)')
|
||||
group.add_argument('--tsan', dest='tsan', action='store_true',
|
||||
help='run a subset of test cases that are proper for the TSAN test')
|
||||
group.add_argument('--fail-env-changed', action='store_true',
|
||||
help='if a test file alters the environment, mark '
|
||||
'the test as failed')
|
||||
|
|
|
@ -18,6 +18,7 @@ from .results import TestResults, EXITCODE_INTERRUPTED
|
|||
from .runtests import RunTests, HuntRefleak
|
||||
from .setup import setup_process, setup_test_dir
|
||||
from .single import run_single_test, PROGRESS_MIN_TIME
|
||||
from .tsan import setup_tsan_tests
|
||||
from .utils import (
|
||||
StrPath, StrJSON, TestName, TestList, TestTuple, TestFilter,
|
||||
strip_py_suffix, count, format_duration,
|
||||
|
@ -56,6 +57,7 @@ class Regrtest:
|
|||
self.quiet: bool = ns.quiet
|
||||
self.pgo: bool = ns.pgo
|
||||
self.pgo_extended: bool = ns.pgo_extended
|
||||
self.tsan: bool = ns.tsan
|
||||
|
||||
# Test results
|
||||
self.results: TestResults = TestResults()
|
||||
|
@ -182,6 +184,9 @@ class Regrtest:
|
|||
# add default PGO tests if no tests are specified
|
||||
setup_pgo_tests(self.cmdline_args, self.pgo_extended)
|
||||
|
||||
if self.tsan:
|
||||
setup_tsan_tests(self.cmdline_args)
|
||||
|
||||
exclude_tests = set()
|
||||
if self.exclude:
|
||||
for arg in self.cmdline_args:
|
||||
|
|
31
Lib/test/libregrtest/tsan.py
Normal file
31
Lib/test/libregrtest/tsan.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Set of tests run by default if --tsan is specified. The tests below were
|
||||
# chosen because they use threads and run in a reasonable amount of time.
|
||||
|
||||
TSAN_TESTS = [
|
||||
'test_capi',
|
||||
'test_code',
|
||||
'test_enum',
|
||||
'test_functools',
|
||||
'test_httpservers',
|
||||
'test_imaplib',
|
||||
'test_importlib',
|
||||
'test_io',
|
||||
'test_logging',
|
||||
'test_queue',
|
||||
'test_signal',
|
||||
'test_socket',
|
||||
'test_sqlite3',
|
||||
'test_ssl',
|
||||
'test_syslog',
|
||||
'test_thread',
|
||||
'test_threadedtempfile',
|
||||
'test_threading',
|
||||
'test_threading_local',
|
||||
'test_threadsignals',
|
||||
'test_weakref',
|
||||
]
|
||||
|
||||
|
||||
def setup_tsan_tests(cmdline_args):
|
||||
if not cmdline_args:
|
||||
cmdline_args[:] = TSAN_TESTS[:]
|
|
@ -64,8 +64,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:]
|
||||
|
|
|
@ -47,6 +47,8 @@ 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
|
||||
|
||||
|
||||
|
@ -384,6 +386,10 @@ class ThreadTests(BaseTestCase):
|
|||
# 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:
|
||||
|
@ -416,6 +422,11 @@ class ThreadTests(BaseTestCase):
|
|||
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
|
||||
|
||||
|
@ -1223,6 +1234,11 @@ class ThreadJoinOnShutdown(BaseTestCase):
|
|||
# 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
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Add --tsan to test.regrtest for running TSAN tests in reasonable execution
|
||||
times. Patch by Donghee Na.
|
|
@ -580,8 +580,8 @@ check_pyobject_forbidden_bytes_is_freed(PyObject *self,
|
|||
static PyObject *
|
||||
check_pyobject_freed_is_freed(PyObject *self, PyObject *Py_UNUSED(args))
|
||||
{
|
||||
/* This test would fail if run with the address sanitizer */
|
||||
#ifdef _Py_ADDRESS_SANITIZER
|
||||
/* ASan or TSan would report an use-after-free error */
|
||||
#if defined(_Py_ADDRESS_SANITIZER) || defined(_Py_THREAD_SANITIZER)
|
||||
Py_RETURN_NONE;
|
||||
#else
|
||||
PyObject *op = PyObject_CallNoArgs((PyObject *)&PyBaseObject_Type);
|
||||
|
|
3
Tools/tsan/supressions.txt
Normal file
3
Tools/tsan/supressions.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
## reference: https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions
|
||||
race:get_allocator_unlocked
|
||||
race:set_allocator_unlocked
|
Loading…
Add table
Add a link
Reference in a new issue