3535platforms_to_skip = ('netbsd5' , 'hp-ux11' )
3636
3737
38+ # gh-89363: Skip fork() test if Python is built with Address Sanitizer (ASAN)
39+ # to work around a libasan race condition, dead lock in pthread_create().
40+ skip_if_asan_fork = support .skip_if_sanitizer (
41+ "libasan has a pthread_create() dead lock" ,
42+ address = True )
43+
44+
45+ def skip_unless_reliable_fork (test ):
46+ if not support .has_fork_support :
47+ return unittest .skip ("requires working os.fork()" )(test )
48+ if sys .platform in platforms_to_skip :
49+ return unittest .skip ("due to known OS bug related to thread+fork" )(test )
50+ if support .check_sanitizer (address = True ):
51+ return unittest .skip ("libasan has a pthread_create() dead lock related to thread+fork" )(test )
52+ return test
53+
54+
3855def restore_default_excepthook (testcase ):
3956 testcase .addCleanup (setattr , threading , 'excepthook' , threading .excepthook )
4057 threading .excepthook = threading .__excepthook__
@@ -539,7 +556,7 @@ def test_daemon_param(self):
539556 t = threading .Thread (daemon = True )
540557 self .assertTrue (t .daemon )
541558
542- @support . requires_fork ()
559+ @skip_unless_reliable_fork
543560 def test_dummy_thread_after_fork (self ):
544561 # Issue #14308: a dummy thread in the active list doesn't mess up
545562 # the after-fork mechanism.
@@ -571,11 +588,7 @@ def background_thread(evt):
571588 self .assertEqual (out , b'' )
572589 self .assertEqual (err , b'' )
573590
574- @support .requires_fork ()
575- # gh-89363: Skip multiprocessing tests if Python is built with ASAN to
576- # work around a libasan race condition: dead lock in pthread_create().
577- @support .skip_if_sanitizer ("libasan has a pthread_create() dead lock" ,
578- address = True )
591+ @skip_unless_reliable_fork
579592 def test_is_alive_after_fork (self ):
580593 # Try hard to trigger #18418: is_alive() could sometimes be True on
581594 # threads that vanished after a fork.
@@ -611,7 +624,7 @@ def f():
611624 th .start ()
612625 th .join ()
613626
614- @support . requires_fork ()
627+ @skip_unless_reliable_fork
615628 @unittest .skipUnless (hasattr (os , 'waitpid' ), "test needs os.waitpid()" )
616629 def test_main_thread_after_fork (self ):
617630 code = """if 1:
@@ -632,8 +645,7 @@ def test_main_thread_after_fork(self):
632645 self .assertEqual (err , b"" )
633646 self .assertEqual (data , "MainThread\n True\n True\n " )
634647
635- @unittest .skipIf (sys .platform in platforms_to_skip , "due to known OS bug" )
636- @support .requires_fork ()
648+ @skip_unless_reliable_fork
637649 @unittest .skipUnless (hasattr (os , 'waitpid' ), "test needs os.waitpid()" )
638650 def test_main_thread_after_fork_from_nonmain_thread (self ):
639651 code = """if 1:
@@ -1080,8 +1092,7 @@ def test_1_join_on_shutdown(self):
10801092 """
10811093 self ._run_and_join (script )
10821094
1083- @support .requires_fork ()
1084- @unittest .skipIf (sys .platform in platforms_to_skip , "due to known OS bug" )
1095+ @skip_unless_reliable_fork
10851096 def test_2_join_in_forked_process (self ):
10861097 # Like the test above, but from a forked interpreter
10871098 script = """if 1:
@@ -1101,8 +1112,7 @@ def test_2_join_in_forked_process(self):
11011112 """
11021113 self ._run_and_join (script )
11031114
1104- @support .requires_fork ()
1105- @unittest .skipIf (sys .platform in platforms_to_skip , "due to known OS bug" )
1115+ @skip_unless_reliable_fork
11061116 def test_3_join_in_forked_from_thread (self ):
11071117 # Like the test above, but fork() was called from a worker thread
11081118 # In the forked process, the main Thread object must be marked as stopped.
@@ -1172,8 +1182,7 @@ def main():
11721182 rc , out , err = assert_python_ok ('-c' , script )
11731183 self .assertFalse (err )
11741184
1175- @support .requires_fork ()
1176- @unittest .skipIf (sys .platform in platforms_to_skip , "due to known OS bug" )
1185+ @skip_unless_reliable_fork
11771186 def test_reinit_tls_after_fork (self ):
11781187 # Issue #13817: fork() would deadlock in a multithreaded program with
11791188 # the ad-hoc TLS implementation.
@@ -1199,7 +1208,7 @@ def do_fork_and_wait():
11991208 for t in threads :
12001209 t .join ()
12011210
1202- @support . requires_fork ()
1211+ @skip_unless_reliable_fork
12031212 def test_clear_threads_states_after_fork (self ):
12041213 # Issue #17094: check that threads states are cleared after fork()
12051214
0 commit comments