Author vstinner
Recipients vstinner
Date 2020-04-01.17:05:27
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <>
On Windows, the exit code is a 32-bit value. It may or may not signed depending on the function.

Unsigned in the Windows native API:

BOOL TerminateProcess(HANDLE hProcess, UINT uExitCode);
BOOL GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode);

Signed in the POSIX API:

intptr_t _cwait(int *termstat, intptr_t procHandle, int action);

Problem: os.waitpid() uses "status << 8" which can overflow; status is an int.

static PyObject *
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
    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);

int64_t or uint64_t should be used, or a Python object should be used, to avoid the overflow.

I just added os.waitstatus_to_exitcode() in bpo-40094 which simply does "status >> 8" on Windows. Currently, this function casts the argument to a C int and so is limited to INT_MAX. It should also be adapted to handle values larger than INT_MAX.

By the way, I'm not sure how to handle values larger than INT_MAX. The POSIX API of Windows uses a signed integer, and so convert such value as a negative value. But the native Windows API uses unsigned numbers.

It seems like using unsigned number would be better.


By the way, currently os.waitstatus_to_exitcode() ignores the lower 8 bits of the status. Maybe it should raise an error if lower 8 bits are not zero, and maybe also raise an exception if the number is negative?


See also interesting comments by Eryk Sun in bpo-40094 about this problem.
Date User Action Args
2020-04-01 17:05:27vstinnersetrecipients: + vstinner
2020-04-01 17:05:27vstinnersetmessageid: <>
2020-04-01 17:05:27vstinnerlinkissue40138 messages
2020-04-01 17:05:27vstinnercreate