|
21 | 21 | import ctypes |
22 | 22 | except ImportError: |
23 | 23 | ctypes = None |
| 24 | +else: |
| 25 | + import ctypes.util |
24 | 26 |
|
25 | 27 | try: |
26 | 28 | import threading |
@@ -2565,43 +2567,40 @@ def test_communicate_BrokenPipeError_stdin_close_with_timeout(self): |
2565 | 2567 | proc.communicate(timeout=999) |
2566 | 2568 | mock_proc_stdin.close.assert_called_once_with() |
2567 | 2569 |
|
2568 | | - _libc_file_extensions = { |
2569 | | - 'Linux': 'so.6', |
2570 | | - 'Darwin': 'dylib', |
2571 | | - } |
2572 | | - @unittest.skipIf(not ctypes, 'ctypes module required.') |
2573 | | - @unittest.skipIf(platform.uname()[0] not in _libc_file_extensions, |
2574 | | - 'Test requires a libc this code can load with ctypes.') |
2575 | | - @unittest.skipIf(not sys.executable, 'Test requires sys.executable.') |
| 2570 | + @unittest.skipIf(not ctypes, 'ctypes module required') |
| 2571 | + @unittest.skipIf(not sys.executable, 'Test requires sys.executable') |
2576 | 2572 | def test_child_terminated_in_stopped_state(self): |
2577 | 2573 | """Test wait() behavior when waitpid returns WIFSTOPPED; issue29335.""" |
2578 | 2574 | PTRACE_TRACEME = 0 # From glibc and MacOS (PT_TRACE_ME). |
2579 | | - libc_name = 'libc.' + self._libc_file_extensions[platform.uname()[0]] |
| 2575 | + libc_name = ctypes.util.find_library('c') |
2580 | 2576 | libc = ctypes.CDLL(libc_name) |
2581 | 2577 | if not hasattr(libc, 'ptrace'): |
2582 | | - raise unittest.SkipTest('ptrace() required.') |
2583 | | - test_ptrace = subprocess.Popen( |
2584 | | - [sys.executable, '-c', """if True: |
2585 | | - import ctypes |
2586 | | - libc = ctypes.CDLL({libc_name!r}) |
2587 | | - libc.ptrace({PTRACE_TRACEME}, 0, 0) |
2588 | | - """.format(libc_name=libc_name, PTRACE_TRACEME=PTRACE_TRACEME) |
2589 | | - ]) |
2590 | | - if test_ptrace.wait() != 0: |
2591 | | - raise unittest.SkipTest('ptrace() failed - unable to test.') |
2592 | | - child = subprocess.Popen( |
2593 | | - [sys.executable, '-c', """if True: |
| 2578 | + raise unittest.SkipTest('ptrace() required') |
| 2579 | + |
| 2580 | + code = textwrap.dedent(f""" |
2594 | 2581 | import ctypes |
| 2582 | + import faulthandler |
| 2583 | + from test.support import SuppressCrashReport |
| 2584 | +
|
2595 | 2585 | libc = ctypes.CDLL({libc_name!r}) |
2596 | 2586 | libc.ptrace({PTRACE_TRACEME}, 0, 0) |
2597 | | - libc.printf(ctypes.c_char_p(0xdeadbeef)) # Crash the process. |
2598 | | - """.format(libc_name=libc_name, PTRACE_TRACEME=PTRACE_TRACEME) |
2599 | | - ]) |
| 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]) |
2600 | 2599 | try: |
2601 | 2600 | returncode = child.wait() |
2602 | | - except Exception as e: |
| 2601 | + except: |
2603 | 2602 | child.kill() # Clean up the hung stopped process. |
2604 | | - raise e |
| 2603 | + raise |
2605 | 2604 | self.assertNotEqual(0, returncode) |
2606 | 2605 | self.assertLess(returncode, 0) # signal death, likely SIGSEGV. |
2607 | 2606 |
|
|
0 commit comments