@@ -138,6 +138,12 @@ def test_all_basic_tests_completeness():
138138 assert len (ALL_BASIC_TESTS ) == num_found
139139
140140
141+ # Issue #2754:
142+ ThreadSanitizer_exitcode_66_message = (
143+ "ThreadSanitizer: starting new threads after multi-threaded fork is not supported."
144+ )
145+
146+
141147def _run_in_process (target , * args , ** kwargs ):
142148 """Runs target in process and returns its exitcode after 10s (None if still alive)."""
143149 process = multiprocessing .Process (target = target , args = args , kwargs = kwargs )
@@ -146,6 +152,8 @@ def _run_in_process(target, *args, **kwargs):
146152 process .start ()
147153 # Do not need to wait much, 10s should be more than enough.
148154 process .join (timeout = 10 )
155+ if process .exitcode == 66 :
156+ pass # NICE-TO-HAVE: Check output for ThreadSanitizer_exitcode_66_message
149157 return process .exitcode
150158 finally :
151159 if process .is_alive ():
@@ -166,26 +174,20 @@ def _run_in_threads(target, num_threads, parallel):
166174 thread .join ()
167175
168176
169- # m.defined_THREAD_SANITIZER is used below to skip tests triggering this error (#2754):
170- # ThreadSanitizer: starting new threads after multi-threaded fork is not supported.
171-
172177# TODO: FIXME, sometimes returns -11 (segfault) instead of 0 on macOS Python 3.9
173- @pytest .mark .skipif (
174- m .defined_THREAD_SANITIZER , reason = "Not compatible with ThreadSanitizer"
175- )
176178@pytest .mark .parametrize ("test_fn" , ALL_BASIC_TESTS )
177179def test_run_in_process_one_thread (test_fn ):
178180 """Makes sure there is no GIL deadlock when running in a thread.
179181
180182 It runs in a separate process to be able to stop and assert if it deadlocks.
181183 """
182- assert _run_in_process (_run_in_threads , test_fn , num_threads = 1 , parallel = False ) == 0
184+ exitcode = _run_in_process (_run_in_threads , test_fn , num_threads = 1 , parallel = False )
185+ if exitcode == 66 and m .defined_THREAD_SANITIZER :
186+ pytest .skip (ThreadSanitizer_exitcode_66_message )
187+ assert exitcode == 0
183188
184189
185190# TODO: FIXME on macOS Python 3.9
186- @pytest .mark .skipif (
187- m .defined_THREAD_SANITIZER , reason = "Not compatible with ThreadSanitizer"
188- )
189191@pytest .mark .parametrize ("test_fn" , ALL_BASIC_TESTS )
190192def test_run_in_process_multiple_threads_parallel (test_fn ):
191193 """Makes sure there is no GIL deadlock when running in a thread multiple times in parallel.
@@ -195,20 +197,22 @@ def test_run_in_process_multiple_threads_parallel(test_fn):
195197 exitcode = _run_in_process (_run_in_threads , test_fn , num_threads = 8 , parallel = True )
196198 if exitcode is None and env .PYPY and env .WIN : # Seems to be flaky.
197199 pytest .skip ("Ignoring unexpected exitcode None (PYPY WIN)" )
200+ if exitcode == 66 and m .defined_THREAD_SANITIZER :
201+ pytest .skip (ThreadSanitizer_exitcode_66_message )
198202 assert exitcode == 0
199203
200204
201205# TODO: FIXME on macOS Python 3.9
202- @pytest .mark .skipif (
203- m .defined_THREAD_SANITIZER , reason = "Not compatible with ThreadSanitizer"
204- )
205206@pytest .mark .parametrize ("test_fn" , ALL_BASIC_TESTS )
206207def test_run_in_process_multiple_threads_sequential (test_fn ):
207208 """Makes sure there is no GIL deadlock when running in a thread multiple times sequentially.
208209
209210 It runs in a separate process to be able to stop and assert if it deadlocks.
210211 """
211- assert _run_in_process (_run_in_threads , test_fn , num_threads = 8 , parallel = False ) == 0
212+ exitcode = _run_in_process (_run_in_threads , test_fn , num_threads = 8 , parallel = False )
213+ if exitcode == 66 and m .defined_THREAD_SANITIZER :
214+ pytest .skip (ThreadSanitizer_exitcode_66_message )
215+ assert exitcode == 0
212216
213217
214218# TODO: FIXME on macOS Python 3.9
@@ -218,15 +222,9 @@ def test_run_in_process_direct(test_fn):
218222
219223 This test is for completion, but it was never an issue.
220224 """
221- if m .defined_THREAD_SANITIZER and test_fn in (
222- test_cross_module_gil_nested_custom_released ,
223- test_cross_module_gil_nested_custom_acquired ,
224- test_cross_module_gil_nested_pybind11_released ,
225- test_cross_module_gil_nested_pybind11_acquired ,
226- test_multi_acquire_release_cross_module ,
227- ):
228- pytest .skip ("Not compatible with ThreadSanitizer" )
229225 exitcode = _run_in_process (test_fn )
230226 if exitcode is None and env .PYPY and env .WIN : # Seems to be flaky.
231227 pytest .skip ("Ignoring unexpected exitcode None (PYPY WIN)" )
228+ if exitcode == 66 and m .defined_THREAD_SANITIZER :
229+ pytest .skip (ThreadSanitizer_exitcode_66_message )
232230 assert exitcode == 0
0 commit comments