6969except ImportError :
7070 INT_MAX = PY_SSIZE_T_MAX = sys .maxsize
7171
72+ try :
73+ import _testcapi
74+ except ImportError :
75+ _testcapi = None
7276
7377from test .support .script_helper import assert_python_ok
7478from test .support import unix_shell
@@ -3067,11 +3071,13 @@ def check_waitpid(self, code, exitcode, callback=None):
30673071 self .assertEqual (pid2 , pid )
30683072
30693073 # TODO: RUSTPYTHON (AttributeError: module 'os' has no attribute 'spawnv')
3074+ @unittest .skipUnless (hasattr (threading .Lock (), '_at_fork_reinit' ), 'TODO: RUSTPYTHON, test needs lock._at_fork_reinit' )
30703075 @unittest .expectedFailure
30713076 def test_waitpid (self ):
30723077 self .check_waitpid (code = 'pass' , exitcode = 0 )
30733078
30743079 # TODO: RUSTPYTHON (AttributeError: module 'os' has no attribute 'spawnv')
3080+ @unittest .skipUnless (hasattr (threading .Lock (), '_at_fork_reinit' ), 'TODO: RUSTPYTHON, test needs lock._at_fork_reinit' )
30753081 @unittest .expectedFailure
30763082 def test_waitstatus_to_exitcode (self ):
30773083 exitcode = 23
@@ -3103,7 +3109,8 @@ def test_waitstatus_to_exitcode_windows(self):
31033109 os .waitstatus_to_exitcode ((max_exitcode + 1 ) << 8 )
31043110 with self .assertRaises (OverflowError ):
31053111 os .waitstatus_to_exitcode (- 1 )
3106-
3112+
3113+ @unittest .skipUnless (hasattr (threading .Lock (), '_at_fork_reinit' ), 'TODO: RUSTPYTHON, test needs lock._at_fork_reinit' )
31073114 # TODO: RUSTPYTHON (AttributeError: module 'os' has no attribute 'spawnv')
31083115 @unittest .expectedFailure
31093116 # Skip the test on Windows
@@ -3146,31 +3153,36 @@ def create_args(self, *, with_env=False, use_bytes=False):
31463153 for k , v in self .env .items ()}
31473154
31483155 return args
3149-
3156+
3157+ @unittest .skipUnless (hasattr (threading .Lock (), '_at_fork_reinit' ), 'TODO: RUSTPYTHON, test needs lock._at_fork_reinit' )
31503158 @requires_os_func ('spawnl' )
31513159 def test_spawnl (self ):
31523160 args = self .create_args ()
31533161 exitcode = os .spawnl (os .P_WAIT , args [0 ], * args )
31543162 self .assertEqual (exitcode , self .exitcode )
31553163
3164+ @unittest .skipUnless (hasattr (threading .Lock (), '_at_fork_reinit' ), 'TODO: RUSTPYTHON, test needs lock._at_fork_reinit' )
31563165 @requires_os_func ('spawnle' )
31573166 def test_spawnle (self ):
31583167 args = self .create_args (with_env = True )
31593168 exitcode = os .spawnle (os .P_WAIT , args [0 ], * args , self .env )
31603169 self .assertEqual (exitcode , self .exitcode )
31613170
3171+ @unittest .skipUnless (hasattr (threading .Lock (), '_at_fork_reinit' ), 'TODO: RUSTPYTHON, test needs lock._at_fork_reinit' )
31623172 @requires_os_func ('spawnlp' )
31633173 def test_spawnlp (self ):
31643174 args = self .create_args ()
31653175 exitcode = os .spawnlp (os .P_WAIT , args [0 ], * args )
31663176 self .assertEqual (exitcode , self .exitcode )
31673177
3178+ @unittest .skipUnless (hasattr (threading .Lock (), '_at_fork_reinit' ), 'TODO: RUSTPYTHON, test needs lock._at_fork_reinit' )
31683179 @requires_os_func ('spawnlpe' )
31693180 def test_spawnlpe (self ):
31703181 args = self .create_args (with_env = True )
31713182 exitcode = os .spawnlpe (os .P_WAIT , args [0 ], * args , self .env )
31723183 self .assertEqual (exitcode , self .exitcode )
31733184
3185+ @unittest .skipUnless (hasattr (threading .Lock (), '_at_fork_reinit' ), 'TODO: RUSTPYTHON, test needs lock._at_fork_reinit' )
31743186 @requires_os_func ('spawnv' )
31753187 def test_spawnv (self ):
31763188 args = self .create_args ()
@@ -3181,30 +3193,35 @@ def test_spawnv(self):
31813193 exitcode = os .spawnv (os .P_WAIT , FakePath (args [0 ]), args )
31823194 self .assertEqual (exitcode , self .exitcode )
31833195
3196+ @unittest .skipUnless (hasattr (threading .Lock (), '_at_fork_reinit' ), 'TODO: RUSTPYTHON, test needs lock._at_fork_reinit' )
31843197 @requires_os_func ('spawnve' )
31853198 def test_spawnve (self ):
31863199 args = self .create_args (with_env = True )
31873200 exitcode = os .spawnve (os .P_WAIT , args [0 ], args , self .env )
31883201 self .assertEqual (exitcode , self .exitcode )
31893202
3203+ @unittest .skipUnless (hasattr (threading .Lock (), '_at_fork_reinit' ), 'TODO: RUSTPYTHON, test needs lock._at_fork_reinit' )
31903204 @requires_os_func ('spawnvp' )
31913205 def test_spawnvp (self ):
31923206 args = self .create_args ()
31933207 exitcode = os .spawnvp (os .P_WAIT , args [0 ], args )
31943208 self .assertEqual (exitcode , self .exitcode )
31953209
3210+ @unittest .skipUnless (hasattr (threading .Lock (), '_at_fork_reinit' ), 'TODO: RUSTPYTHON, test needs lock._at_fork_reinit' )
31963211 @requires_os_func ('spawnvpe' )
31973212 def test_spawnvpe (self ):
31983213 args = self .create_args (with_env = True )
31993214 exitcode = os .spawnvpe (os .P_WAIT , args [0 ], args , self .env )
32003215 self .assertEqual (exitcode , self .exitcode )
32013216
3217+ @unittest .skipUnless (hasattr (threading .Lock (), '_at_fork_reinit' ), 'TODO: RUSTPYTHON, test needs lock._at_fork_reinit' )
32023218 @requires_os_func ('spawnv' )
32033219 def test_nowait (self ):
32043220 args = self .create_args ()
32053221 pid = os .spawnv (os .P_NOWAIT , args [0 ], args )
32063222 support .wait_process (pid , exitcode = self .exitcode )
32073223
3224+ @unittest .skipUnless (hasattr (threading .Lock (), '_at_fork_reinit' ), 'TODO: RUSTPYTHON, test needs lock._at_fork_reinit' )
32083225 @requires_os_func ('spawnve' )
32093226 def test_spawnve_bytes (self ):
32103227 # Test bytes handling in parse_arglist and parse_envlist (#28114)
@@ -3286,10 +3303,12 @@ def _test_invalid_env(self, spawn):
32863303 exitcode = spawn (os .P_WAIT , args [0 ], args , newenv )
32873304 self .assertEqual (exitcode , 0 )
32883305
3306+ @unittest .skipUnless (hasattr (threading .Lock (), '_at_fork_reinit' ), 'TODO: RUSTPYTHON, test needs lock._at_fork_reinit' )
32893307 @requires_os_func ('spawnve' )
32903308 def test_spawnve_invalid_env (self ):
32913309 self ._test_invalid_env (os .spawnve )
32923310
3311+ @unittest .skipUnless (hasattr (threading .Lock (), '_at_fork_reinit' ), 'TODO: RUSTPYTHON, test needs lock._at_fork_reinit' )
32933312 @requires_os_func ('spawnvpe' )
32943313 def test_spawnvpe_invalid_env (self ):
32953314 self ._test_invalid_env (os .spawnvpe )
@@ -4660,6 +4679,35 @@ def test_fork(self):
46604679 assert_python_ok ("-c" , code )
46614680 assert_python_ok ("-c" , code , PYTHONMALLOC = "malloc_debug" )
46624681
4682+ @unittest .skipIf (_testcapi is None , 'TODO: RUSTPYTHON; needs _testcapi' )
4683+ @unittest .skipUnless (sys .platform in ("linux" , "darwin" ),
4684+ "Only Linux and macOS detect this today." )
4685+ def test_fork_warns_when_non_python_thread_exists (self ):
4686+ code = """if 1:
4687+ import os, threading, warnings
4688+ from _testcapi import _spawn_pthread_waiter, _end_spawned_pthread
4689+ _spawn_pthread_waiter()
4690+ try:
4691+ with warnings.catch_warnings(record=True) as ws:
4692+ warnings.filterwarnings(
4693+ "always", category=DeprecationWarning)
4694+ if os.fork() == 0:
4695+ assert not ws, f"unexpected warnings in child: {ws}"
4696+ os._exit(0) # child
4697+ else:
4698+ assert ws[0].category == DeprecationWarning, ws[0]
4699+ assert 'fork' in str(ws[0].message), ws[0]
4700+ # Waiting allows an error in the child to hit stderr.
4701+ exitcode = os.wait()[1]
4702+ assert exitcode == 0, f"child exited {exitcode}"
4703+ assert threading.active_count() == 1, threading.enumerate()
4704+ finally:
4705+ _end_spawned_pthread()
4706+ """
4707+ _ , out , err = assert_python_ok ("-c" , code , PYTHONOPTIMIZE = '0' )
4708+ self .assertEqual (err .decode ("utf-8" ), "" )
4709+ self .assertEqual (out .decode ("utf-8" ), "" )
4710+
46634711
46644712# Only test if the C version is provided, otherwise TestPEP519 already tested
46654713# the pure Python implementation.
0 commit comments