33"""
44
55import test .support
6- from test .support import threading_helper
6+ from test .support import threading_helper , requires_subprocess
77from test .support import verbose , cpython_only , os_helper
88from test .support .import_helper import import_module
99from test .support .script_helper import assert_python_ok , assert_python_failure
2525from test import lock_tests
2626from test import support
2727
28+ threading_helper .requires_working_threading (module = True )
2829
2930# Between fork() and exec(), only async-safe functions are allowed (issues
3031# #12316 and #11870), and fork() from a worker thread is known to trigger
3132# problems with some operating systems (issue #3863): skip problematic tests
3233# on platforms known to behave badly.
3334platforms_to_skip = ('netbsd5' , 'hp-ux11' )
3435
35- # Is Python built with Py_DEBUG macro defined?
36- Py_DEBUG = hasattr (sys , 'gettotalrefcount' )
37-
3836
3937def restore_default_excepthook (testcase ):
4038 testcase .addCleanup (setattr , threading , 'excepthook' , threading .excepthook )
@@ -123,6 +121,33 @@ def func(): pass
123121 thread = threading .Thread (target = func )
124122 self .assertEqual (thread .name , "Thread-5 (func)" )
125123
124+ def test_args_argument (self ):
125+ # bpo-45735: Using list or tuple as *args* in constructor could
126+ # achieve the same effect.
127+ num_list = [1 ]
128+ num_tuple = (1 ,)
129+
130+ str_list = ["str" ]
131+ str_tuple = ("str" ,)
132+
133+ list_in_tuple = ([1 ],)
134+ tuple_in_list = [(1 ,)]
135+
136+ test_cases = (
137+ (num_list , lambda arg : self .assertEqual (arg , 1 )),
138+ (num_tuple , lambda arg : self .assertEqual (arg , 1 )),
139+ (str_list , lambda arg : self .assertEqual (arg , "str" )),
140+ (str_tuple , lambda arg : self .assertEqual (arg , "str" )),
141+ (list_in_tuple , lambda arg : self .assertEqual (arg , [1 ])),
142+ (tuple_in_list , lambda arg : self .assertEqual (arg , (1 ,)))
143+ )
144+
145+ for args , target in test_cases :
146+ with self .subTest (target = target , args = args ):
147+ t = threading .Thread (target = target , args = args )
148+ t .start ()
149+ t .join ()
150+
126151 @cpython_only
127152 def test_disallow_instantiation (self ):
128153 # Ensure that the type disallows instantiation (bpo-43916)
@@ -509,8 +534,7 @@ def test_daemon_param(self):
509534 t = threading .Thread (daemon = True )
510535 self .assertTrue (t .daemon )
511536
512- @unittest .skipUnless (hasattr (threading .Lock (), '_at_fork_reinit' ), 'TODO: RUSTPYTHON, exit_handler needs lock._at_fork_reinit' )
513- @unittest .skipUnless (hasattr (os , 'fork' ), 'needs os.fork()' )
537+ @support .requires_fork ()
514538 def test_fork_at_exit (self ):
515539 # bpo-42350: Calling os.fork() after threading._shutdown() must
516540 # not log an error.
@@ -538,7 +562,7 @@ def exit_handler():
538562 self .assertEqual (out , b'' )
539563 self .assertEqual (err .rstrip (), b'child process ok' )
540564
541- @unittest . skipUnless ( hasattr ( os , 'fork' ), 'test needs fork()' )
565+ @support . requires_fork ( )
542566 def test_dummy_thread_after_fork (self ):
543567 # Issue #14308: a dummy thread in the active list doesn't mess up
544568 # the after-fork mechanism.
@@ -565,8 +589,7 @@ def background_thread(evt):
565589 self .assertEqual (out , b'' )
566590 self .assertEqual (err , b'' )
567591
568- @unittest .skipUnless (hasattr (sys , 'getswitchinterval' ), "TODO: RUSTPYTHON, needs sys.getswitchinterval()" )
569- @unittest .skipUnless (hasattr (os , 'fork' ), "needs os.fork()" )
592+ @support .requires_fork ()
570593 def test_is_alive_after_fork (self ):
571594 # Try hard to trigger #18418: is_alive() could sometimes be True on
572595 # threads that vanished after a fork.
@@ -600,7 +623,7 @@ def f():
600623 th .start ()
601624 th .join ()
602625
603- @unittest . skipUnless ( hasattr ( os , 'fork' ), "test needs os.fork()" )
626+ @support . requires_fork ( )
604627 @unittest .skipUnless (hasattr (os , 'waitpid' ), "test needs os.waitpid()" )
605628 def test_main_thread_after_fork (self ):
606629 code = """if 1:
@@ -622,7 +645,7 @@ def test_main_thread_after_fork(self):
622645 self .assertEqual (data , "MainThread\n True\n True\n " )
623646
624647 @unittest .skipIf (sys .platform in platforms_to_skip , "due to known OS bug" )
625- @unittest . skipUnless ( hasattr ( os , 'fork' ), "test needs os.fork()" )
648+ @support . requires_fork ( )
626649 @unittest .skipUnless (hasattr (os , 'waitpid' ), "test needs os.waitpid()" )
627650 @unittest .skipIf (os .name != 'posix' , "test needs POSIX semantics" )
628651 def test_main_thread_after_fork_from_nonmain_thread (self ):
@@ -837,6 +860,7 @@ def callback():
837860 callback ()
838861 finally :
839862 sys .settrace (old_trace )
863+ threading .settrace (old_trace )
840864
841865 def test_gettrace (self ):
842866 def noop_trace (frame , event , arg ):
@@ -850,6 +874,37 @@ def noop_trace(frame, event, arg):
850874 finally :
851875 threading .settrace (old_trace )
852876
877+ # TODO: RUSTPYTHON
878+ @unittest .expectedFailure
879+ def test_gettrace_all_threads (self ):
880+ def fn (* args ): pass
881+ old_trace = threading .gettrace ()
882+ first_check = threading .Event ()
883+ second_check = threading .Event ()
884+
885+ trace_funcs = []
886+ def checker ():
887+ trace_funcs .append (sys .gettrace ())
888+ first_check .set ()
889+ second_check .wait ()
890+ trace_funcs .append (sys .gettrace ())
891+
892+ try :
893+ t = threading .Thread (target = checker )
894+ t .start ()
895+ first_check .wait ()
896+ threading .settrace_all_threads (fn )
897+ second_check .set ()
898+ t .join ()
899+ self .assertEqual (trace_funcs , [None , fn ])
900+ self .assertEqual (threading .gettrace (), fn )
901+ self .assertEqual (sys .gettrace (), fn )
902+ finally :
903+ threading .settrace_all_threads (old_trace )
904+
905+ self .assertEqual (threading .gettrace (), old_trace )
906+ self .assertEqual (sys .gettrace (), old_trace )
907+
853908 def test_getprofile (self ):
854909 def fn (* args ): pass
855910 old_profile = threading .getprofile ()
@@ -859,6 +914,37 @@ def fn(*args): pass
859914 finally :
860915 threading .setprofile (old_profile )
861916
917+ # TODO: RUSTPYTHON
918+ @unittest .expectedFailure
919+ def test_getprofile_all_threads (self ):
920+ def fn (* args ): pass
921+ old_profile = threading .getprofile ()
922+ first_check = threading .Event ()
923+ second_check = threading .Event ()
924+
925+ profile_funcs = []
926+ def checker ():
927+ profile_funcs .append (sys .getprofile ())
928+ first_check .set ()
929+ second_check .wait ()
930+ profile_funcs .append (sys .getprofile ())
931+
932+ try :
933+ t = threading .Thread (target = checker )
934+ t .start ()
935+ first_check .wait ()
936+ threading .setprofile_all_threads (fn )
937+ second_check .set ()
938+ t .join ()
939+ self .assertEqual (profile_funcs , [None , fn ])
940+ self .assertEqual (threading .getprofile (), fn )
941+ self .assertEqual (sys .getprofile (), fn )
942+ finally :
943+ threading .setprofile_all_threads (old_profile )
944+
945+ self .assertEqual (threading .getprofile (), old_profile )
946+ self .assertEqual (sys .getprofile (), old_profile )
947+
862948 @cpython_only
863949 def test_shutdown_locks (self ):
864950 for daemon in (False , True ):
@@ -929,16 +1015,6 @@ def noop(): pass
9291015 threading .Thread (target = noop ).start ()
9301016 # Thread.join() is not called
9311017
932- @unittest .skipUnless (Py_DEBUG , 'need debug build (Py_DEBUG)' )
933- def test_debug_deprecation (self ):
934- # bpo-44584: The PYTHONTHREADDEBUG environment variable is deprecated
935- rc , out , err = assert_python_ok ("-Wdefault" , "-c" , "pass" ,
936- PYTHONTHREADDEBUG = "1" )
937- msg = (b'DeprecationWarning: The threading debug '
938- b'(PYTHONTHREADDEBUG environment variable) '
939- b'is deprecated and will be removed in Python 3.12' )
940- self .assertIn (msg , err )
941-
9421018 def test_import_from_another_thread (self ):
9431019 # bpo-1596321: If the threading module is first import from a thread
9441020 # different than the main thread, threading._shutdown() must handle
@@ -1006,7 +1082,7 @@ def test_1_join_on_shutdown(self):
10061082 """
10071083 self ._run_and_join (script )
10081084
1009- @unittest . skipUnless ( hasattr ( os , 'fork' ), "needs os.fork()" )
1085+ @support . requires_fork ( )
10101086 @unittest .skipIf (sys .platform in platforms_to_skip , "due to known OS bug" )
10111087 # TODO: RUSTPYTHON need to fix test_1_join_on_shutdown then this might work
10121088 @unittest .expectedFailure
@@ -1029,7 +1105,7 @@ def test_2_join_in_forked_process(self):
10291105 """
10301106 self ._run_and_join (script )
10311107
1032- @unittest . skipUnless ( hasattr ( os , 'fork' ), "needs os.fork()" )
1108+ @support . requires_fork ( )
10331109 @unittest .skipIf (sys .platform in platforms_to_skip , "due to known OS bug" )
10341110 @unittest .skip ("TODO: RUSTPYTHON, flaky test" )
10351111 def test_3_join_in_forked_from_thread (self ):
@@ -1075,8 +1151,9 @@ def test_4_daemon_threads(self):
10751151
10761152 def random_io():
10771153 '''Loop for a while sleeping random tiny amounts and doing some I/O.'''
1154+ import test.test_threading as mod
10781155 while True:
1079- with open(os .__file__, 'rb') as in_f:
1156+ with open(mod .__file__, 'rb') as in_f:
10801157 stuff = in_f.read(200)
10811158 with open(os.devnull, 'wb') as null_f:
10821159 null_f.write(stuff)
@@ -1100,7 +1177,7 @@ def main():
11001177 rc , out , err = assert_python_ok ('-c' , script )
11011178 self .assertFalse (err )
11021179
1103- @unittest . skipUnless ( hasattr ( os , 'fork' ), "needs os.fork()" )
1180+ @support . requires_fork ( )
11041181 @unittest .skipIf (sys .platform in platforms_to_skip , "due to known OS bug" )
11051182 def test_reinit_tls_after_fork (self ):
11061183 # Issue #13817: fork() would deadlock in a multithreaded program with
@@ -1124,8 +1201,9 @@ def do_fork_and_wait():
11241201 for t in threads :
11251202 t .join ()
11261203
1127- @unittest .skipUnless (hasattr (sys , '_current_frames' ), "TODO: RUSTPYTHON, needs sys._current_frames()" )
1128- @unittest .skipUnless (hasattr (os , 'fork' ), "needs os.fork()" )
1204+ @support .requires_fork ()
1205+ # TODO: RUSTPYTHON
1206+ @unittest .expectedFailure
11291207 def test_clear_threads_states_after_fork (self ):
11301208 # Issue #17094: check that threads states are cleared after fork()
11311209
@@ -1280,6 +1358,7 @@ def test_releasing_unacquired_lock(self):
12801358 self .assertRaises (RuntimeError , lock .release )
12811359
12821360 @unittest .skip ("TODO: RUSTPYTHON, flaky test" )
1361+ @requires_subprocess ()
12831362 def test_recursion_limit (self ):
12841363 # Issue 9670
12851364 # test that excessive recursion within a non-main thread causes
0 commit comments