bpo-31173: Rewrite WSTOPSIG test of test_subprocess (#3055) (#3070) · python/cpython@bc69d00
@@ -29,6 +29,11 @@
2929except ImportError:
3030threading = None
313132+try:
33+import _testcapi
34+except ImportError:
35+_testcapi = None
36+3237if support.PGO:
3338raise unittest.SkipTest("test is not helpful for PGO")
3439@@ -2567,42 +2572,24 @@ def test_communicate_BrokenPipeError_stdin_close_with_timeout(self):
25672572proc.communicate(timeout=999)
25682573mock_proc_stdin.close.assert_called_once_with()
256925742570-@unittest.skipIf(not ctypes, 'ctypes module required')
2571-@unittest.skipIf(not sys.executable, 'Test requires sys.executable')
2572-def test_child_terminated_in_stopped_state(self):
2575+@unittest.skipUnless(_testcapi is not None
2576+ and hasattr(_testcapi, 'W_STOPCODE'),
2577+ 'need _testcapi.W_STOPCODE')
2578+def test_stopped(self):
25732579"""Test wait() behavior when waitpid returns WIFSTOPPED; issue29335."""
2574-PTRACE_TRACEME = 0 # From glibc and MacOS (PT_TRACE_ME).
2575-libc_name = ctypes.util.find_library('c')
2576-libc = ctypes.CDLL(libc_name)
2577-if not hasattr(libc, 'ptrace'):
2578-raise unittest.SkipTest('ptrace() required')
2579-2580-code = textwrap.dedent(f"""
2581- import ctypes
2582- import faulthandler
2583- from test.support import SuppressCrashReport
2584-2585- libc = ctypes.CDLL({libc_name!r})
2586- libc.ptrace({PTRACE_TRACEME}, 0, 0)
2587- """)
2588-2589-child = subprocess.Popen([sys.executable, '-c', code])
2590-if child.wait() != 0:
2591-raise unittest.SkipTest('ptrace() failed - unable to test')
2592-2593-code += textwrap.dedent(f"""
2594- with SuppressCrashReport():
2595- # Crash the process
2596- faulthandler._sigsegv()
2597- """)
2598-child = subprocess.Popen([sys.executable, '-c', code])
2599-try:
2600-returncode = child.wait()
2601-except:
2602-child.kill() # Clean up the hung stopped process.
2603-raise
2604-self.assertNotEqual(0, returncode)
2605-self.assertLess(returncode, 0) # signal death, likely SIGSEGV.
2580+args = [sys.executable, '-c', 'pass']
2581+proc = subprocess.Popen(args)
2582+2583+# Wait until the real process completes to avoid zombie process
2584+pid = proc.pid
2585+pid, status = os.waitpid(pid, 0)
2586+self.assertEqual(status, 0)
2587+2588+status = _testcapi.W_STOPCODE(3)
2589+with mock.patch('subprocess.os.waitpid', return_value=(pid, status)):
2590+returncode = proc.wait()
2591+2592+self.assertEqual(returncode, -3)
260625932607259426082595@unittest.skipUnless(mswindows, "Windows specific tests")