bpo-40138: Fix Windows os.waitpid() for large exit code (GH-19654)
Fix the Windows implementation of os.waitpid() for exit code larger than "INT_MAX >> 8". The exit status is now interpreted as an unsigned number.
This commit is contained in:
parent
3a55450256
commit
b07350901c
|
@ -2675,12 +2675,37 @@ class PidTests(unittest.TestCase):
|
|||
# We are the parent of our subprocess
|
||||
self.assertEqual(int(stdout), os.getpid())
|
||||
|
||||
def check_waitpid(self, code, exitcode):
|
||||
if sys.platform == 'win32':
|
||||
# On Windows, os.spawnv() simply joins arguments with spaces:
|
||||
# arguments need to be quoted
|
||||
args = [f'"{sys.executable}"', '-c', f'"{code}"']
|
||||
else:
|
||||
args = [sys.executable, '-c', code]
|
||||
pid = os.spawnv(os.P_NOWAIT, sys.executable, args)
|
||||
|
||||
pid2, status = os.waitpid(pid, 0)
|
||||
if sys.platform == 'win32':
|
||||
self.assertEqual(status, exitcode << 8)
|
||||
else:
|
||||
self.assertTrue(os.WIFEXITED(status), status)
|
||||
self.assertEqual(os.WEXITSTATUS(status), exitcode)
|
||||
self.assertEqual(pid2, pid)
|
||||
|
||||
def test_waitpid(self):
|
||||
args = [sys.executable, '-c', 'pass']
|
||||
# Add an implicit test for PyUnicode_FSConverter().
|
||||
pid = os.spawnv(os.P_NOWAIT, FakePath(args[0]), args)
|
||||
status = os.waitpid(pid, 0)
|
||||
self.assertEqual(status, (pid, 0))
|
||||
self.check_waitpid(code='pass', exitcode=0)
|
||||
|
||||
def test_waitpid_exitcode(self):
|
||||
exitcode = 23
|
||||
code = f'import sys; sys.exit({exitcode})'
|
||||
self.check_waitpid(code, exitcode=exitcode)
|
||||
|
||||
@unittest.skipUnless(sys.platform == 'win32', 'win32-specific test')
|
||||
def test_waitpid_windows(self):
|
||||
# bpo-40138: test os.waitpid() with exit code larger than INT_MAX.
|
||||
STATUS_CONTROL_C_EXIT = 0xC000013A
|
||||
code = f'import _winapi; _winapi.ExitProcess({STATUS_CONTROL_C_EXIT})'
|
||||
self.check_waitpid(code, exitcode=STATUS_CONTROL_C_EXIT)
|
||||
|
||||
|
||||
class SpawnTests(unittest.TestCase):
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Fix the Windows implementation of :func:`os.waitpid` for exit code larger than
|
||||
``INT_MAX >> 8``. The exit status is now interpreted as an unsigned number.
|
|
@ -7867,8 +7867,10 @@ os_waitpid_impl(PyObject *module, intptr_t pid, int options)
|
|||
if (res < 0)
|
||||
return (!async_err) ? posix_error() : NULL;
|
||||
|
||||
unsigned long long ustatus = (unsigned int)status;
|
||||
|
||||
/* shift the status left a byte so this is more like the POSIX waitpid */
|
||||
return Py_BuildValue(_Py_PARSE_INTPTR "i", res, status << 8);
|
||||
return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue