37
37
Py_DEBUG = hasattr (sys , 'gettotalrefcount' )
38
38
39
39
40
+ # gh-89363: Skip fork() test if Python is built with Address Sanitizer (ASAN)
41
+ # to work around a libasan race condition, dead lock in pthread_create().
42
+ skip_if_asan_fork = support .skip_if_sanitizer (
43
+ "libasan has a pthread_create() dead lock" ,
44
+ address = True )
45
+
46
+
47
+ def skip_unless_reliable_fork (test ):
48
+ if not support .has_fork_support :
49
+ return unittest .skip ("requires working os.fork()" )(test )
50
+ if sys .platform in platforms_to_skip :
51
+ return unittest .skip ("due to known OS bug related to thread+fork" )(test )
52
+ if support .check_sanitizer (address = True ):
53
+ return unittest .skip ("libasan has a pthread_create() dead lock related to thread+fork" )(test )
54
+ return test
55
+
56
+
40
57
def restore_default_excepthook (testcase ):
41
58
testcase .addCleanup (setattr , threading , 'excepthook' , threading .excepthook )
42
59
threading .excepthook = threading .__excepthook__
@@ -533,7 +550,7 @@ def test_daemon_param(self):
533
550
t = threading .Thread (daemon = True )
534
551
self .assertTrue (t .daemon )
535
552
536
- @support . requires_fork ()
553
+ @skip_unless_reliable_fork
537
554
def test_fork_at_exit (self ):
538
555
# bpo-42350: Calling os.fork() after threading._shutdown() must
539
556
# not log an error.
@@ -561,7 +578,7 @@ def exit_handler():
561
578
self .assertEqual (out , b'' )
562
579
self .assertEqual (err .rstrip (), b'child process ok' )
563
580
564
- @support . requires_fork ()
581
+ @skip_unless_reliable_fork
565
582
def test_dummy_thread_after_fork (self ):
566
583
# Issue #14308: a dummy thread in the active list doesn't mess up
567
584
# the after-fork mechanism.
@@ -588,11 +605,7 @@ def background_thread(evt):
588
605
self .assertEqual (out , b'' )
589
606
self .assertEqual (err , b'' )
590
607
591
- @support .requires_fork ()
592
- # gh-89363: Skip multiprocessing tests if Python is built with ASAN to
593
- # work around a libasan race condition: dead lock in pthread_create().
594
- @support .skip_if_sanitizer ("libasan has a pthread_create() dead lock" ,
595
- address = True )
608
+ @skip_unless_reliable_fork
596
609
def test_is_alive_after_fork (self ):
597
610
# Try hard to trigger #18418: is_alive() could sometimes be True on
598
611
# threads that vanished after a fork.
@@ -626,7 +639,7 @@ def f():
626
639
th .start ()
627
640
th .join ()
628
641
629
- @support . requires_fork ()
642
+ @skip_unless_reliable_fork
630
643
@unittest .skipUnless (hasattr (os , 'waitpid' ), "test needs os.waitpid()" )
631
644
def test_main_thread_after_fork (self ):
632
645
code = """if 1:
@@ -647,8 +660,7 @@ def test_main_thread_after_fork(self):
647
660
self .assertEqual (err , b"" )
648
661
self .assertEqual (data , "MainThread\n True\n True\n " )
649
662
650
- @unittest .skipIf (sys .platform in platforms_to_skip , "due to known OS bug" )
651
- @support .requires_fork ()
663
+ @skip_unless_reliable_fork
652
664
@unittest .skipUnless (hasattr (os , 'waitpid' ), "test needs os.waitpid()" )
653
665
def test_main_thread_after_fork_from_nonmain_thread (self ):
654
666
code = """if 1:
@@ -1025,8 +1037,7 @@ def test_1_join_on_shutdown(self):
1025
1037
"""
1026
1038
self ._run_and_join (script )
1027
1039
1028
- @support .requires_fork ()
1029
- @unittest .skipIf (sys .platform in platforms_to_skip , "due to known OS bug" )
1040
+ @skip_unless_reliable_fork
1030
1041
def test_2_join_in_forked_process (self ):
1031
1042
# Like the test above, but from a forked interpreter
1032
1043
script = """if 1:
@@ -1046,8 +1057,7 @@ def test_2_join_in_forked_process(self):
1046
1057
"""
1047
1058
self ._run_and_join (script )
1048
1059
1049
- @support .requires_fork ()
1050
- @unittest .skipIf (sys .platform in platforms_to_skip , "due to known OS bug" )
1060
+ @skip_unless_reliable_fork
1051
1061
def test_3_join_in_forked_from_thread (self ):
1052
1062
# Like the test above, but fork() was called from a worker thread
1053
1063
# In the forked process, the main Thread object must be marked as stopped.
@@ -1117,8 +1127,7 @@ def main():
1117
1127
rc , out , err = assert_python_ok ('-c' , script )
1118
1128
self .assertFalse (err )
1119
1129
1120
- @support .requires_fork ()
1121
- @unittest .skipIf (sys .platform in platforms_to_skip , "due to known OS bug" )
1130
+ @skip_unless_reliable_fork
1122
1131
def test_reinit_tls_after_fork (self ):
1123
1132
# Issue #13817: fork() would deadlock in a multithreaded program with
1124
1133
# the ad-hoc TLS implementation.
@@ -1141,7 +1150,7 @@ def do_fork_and_wait():
1141
1150
for t in threads :
1142
1151
t .join ()
1143
1152
1144
- @support . requires_fork ()
1153
+ @skip_unless_reliable_fork
1145
1154
def test_clear_threads_states_after_fork (self ):
1146
1155
# Issue #17094: check that threads states are cleared after fork()
1147
1156
0 commit comments