bpo-31173: Rewrite WSTOPSIG test of test_subprocess (#3055) (#3070) · python/cpython@bc69d00 (original) (raw)
`@@ -29,6 +29,11 @@
`
29
29
`except ImportError:
`
30
30
`threading = None
`
31
31
``
``
32
`+
try:
`
``
33
`+
import _testcapi
`
``
34
`+
except ImportError:
`
``
35
`+
_testcapi = None
`
``
36
+
32
37
`if support.PGO:
`
33
38
`raise unittest.SkipTest("test is not helpful for PGO")
`
34
39
``
`@@ -2567,42 +2572,24 @@ def test_communicate_BrokenPipeError_stdin_close_with_timeout(self):
`
2567
2572
`proc.communicate(timeout=999)
`
2568
2573
`mock_proc_stdin.close.assert_called_once_with()
`
2569
2574
``
2570
``
`-
@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):
`
2573
2579
`"""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)
`
2606
2593
``
2607
2594
``
2608
2595
`@unittest.skipUnless(mswindows, "Windows specific tests")
`