Skip to content

Commit

Permalink
test: add support for checking for TSAN
Browse files Browse the repository at this point in the history
 - Skip some unsupported tests in test_threading
 - Skip some unsupported tests in test_concurrent_futures
  • Loading branch information
colesbury committed Apr 23, 2023
1 parent cff3269 commit c9fc496
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 3 deletions.
11 changes: 8 additions & 3 deletions Lib/test/support/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,9 +396,9 @@ def skip_if_buildbot(reason=None):
isbuildbot = False
return unittest.skipIf(isbuildbot, reason)

def check_sanitizer(*, address=False, memory=False, ub=False):
def check_sanitizer(*, address=False, memory=False, ub=False, thread=False):
"""Returns True if Python is compiled with sanitizer support"""
if not (address or memory or ub):
if not (address or memory or ub or thread):
raise ValueError('At least one of address, memory, or ub must be True')


Expand All @@ -416,10 +416,15 @@ def check_sanitizer(*, address=False, memory=False, ub=False):
'-fsanitize=undefined' in _cflags or
'--with-undefined-behavior-sanitizer' in _config_args
)
thread_sanitizer = (
'-fsanitize=thread' in _cflags or
'--with-thread-sanitizer' in _config_args
)
return (
(memory and memory_sanitizer) or
(address and address_sanitizer) or
(ub and ub_sanitizer)
(ub and ub_sanitizer) or
(thread and thread_sanitizer)
)


Expand Down
4 changes: 4 additions & 0 deletions Lib/test/test_concurrent_futures.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ def get_context(self):
self.skipTest("ProcessPoolExecutor unavailable on this system")
if sys.platform == "win32":
self.skipTest("require unix system")
if support.check_sanitizer(thread=True):
self.skipTest("TSAN doesn't support threads after fork")
return super().get_context()


Expand All @@ -187,6 +189,8 @@ def get_context(self):
self.skipTest("ProcessPoolExecutor unavailable on this system")
if sys.platform == "win32":
self.skipTest("require unix system")
if support.check_sanitizer(thread=True):
self.skipTest("TSAN doesn't support threads after fork")
return super().get_context()


Expand Down
3 changes: 3 additions & 0 deletions Lib/test/test_threading.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,7 @@ def exit_handler():
self.assertEqual(err.rstrip(), b'child process ok')

@support.requires_fork()
@unittest.skipIf(support.check_sanitizer(thread=True), "TSAN doesn't support threads after 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.
Expand Down Expand Up @@ -653,6 +654,7 @@ def test_main_thread_after_fork(self):
@unittest.skipIf(sys.platform in platforms_to_skip, "due to known OS bug")
@support.requires_fork()
@unittest.skipUnless(hasattr(os, 'waitpid'), "test needs os.waitpid()")
@unittest.skipIf(support.check_sanitizer(thread=True), "TSAN doesn't support threads after fork")
def test_main_thread_after_fork_from_nonmain_thread(self):
code = """if 1:
import os, threading, sys, warnings
Expand Down Expand Up @@ -1071,6 +1073,7 @@ def test_2_join_in_forked_process(self):

@support.requires_fork()
@unittest.skipIf(sys.platform in platforms_to_skip, "due to known OS bug")
@unittest.skipIf(support.check_sanitizer(thread=True), "TSAN doesn't support threads after 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.
Expand Down

0 comments on commit c9fc496

Please sign in to comment.