Author eryksun
Recipients eryksun, vstinner
Date 2020-04-01.09:40:38
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <>
> It's more the opposite, if tomorrow we want to encode the status 
> of a terminated process differently, it will be easier if 
> os.waitstatus_to_exitcode() is available, no?

This new status-to-exitcode function applies to Windows waitpid() only due to a design choice in CPython -- not the operating system. The current waitpid() implementation assumes it's okay to discard the upper 8 bits of the exit status, which can lose important information. Maybe it's best to address Windows support in a new issue that also addresses the design of waitpid() in 3.9, in particular if this would change the design of the new function -- at the very least with regard to data type (e.g. `int status` doesn't have the required range).

Off topic: Despite the function name, waitpid in Windows takes a process handle, such as is returned by os.spawn*, and not a process ID, such as is required by os.kill. The current documentation is sometimes clear on this detail but sometimes confusingly mixes up "handle" and "id" in Windows-only sections.

> The result is a Python object. IMHO it's ok if the shifted result 
> ("status") is larger than 32 bits. But I'm not sure that the 
> current os.waitpid() implementation handles integer overflow 
> correctly...

The overflow problem could be addressed by using a 64-bit value for the status in os_waitpid_impl and elsewhere.

> Do you suggest that os.waitstatus_to_exitcode() result should be 
> negative if a process was terminated by TerminateProcess()?

Returning a signed result is an interesting suggestion. The native process exit status is actually an NTSTATUS value, and NTSTATUS and HRESULT codes are signed, with failure codes (i.e. errors and warnings) reported as negative values. That said, the exit status gets handled as an unsigned value in the Windows API, e.g. ExitProcess, TerminateProcess, and GetExitCodeProcess.

> When I look at GetExitCodeProcess() documentation, I don't see any 
> distinction between "normal exit" and a program terminated by 
> TerminateProcess(). The only different is the actual exit code:

In almost all cases a process terminates via TerminateProcess -- or rather the internal NTAPI function NtTerminateProcess. For a clean exit via ExitProcess (i.e. native RtlExitUserProcess), NtTerminateProcess gets called twice. The first time it gets called specially (with the process handle passed as NULL) in order to forcefully terminate all other threads in the process. Once the thread that calls ExitProcess is the last remaining thread, the loader shuts down the user-mode aspects of the process (e.g. it calls DLL entry points for process detach). Finally, the last thread makes a regular NtTerminateProcess call (with the current-process handle instead of NULL), which actually terminates the process.

An abnormal termination just does the latter step, but it doesn't necessarily use an exit status value that clearly indicates an abnormal termination. Thus not all abnormal terminations can be identified as such. Also, nothing stops a normal termination via ExitProcess from using an NTSTATUS code. For example, the default control handler for a console process exits via ExitProcess with the status code STATUS_CONTROL_C_EXIT (0xC000_013A). This is similar to an abnormal exit, since the process is killed by the closest thing to a Unix 'signal' that Windows console applications support. Moreover, the same status code is used for a genuinely abnormal exit due to a Ctrl+Close event (i.e. the console window was closed) if the session server is forced to terminate a console process that doesn't exit gracefully in the allotted time (default 5 seconds).
Date User Action Args
2020-04-01 09:40:39eryksunsetrecipients: + eryksun, vstinner
2020-04-01 09:40:39eryksunsetmessageid: <>
2020-04-01 09:40:39eryksunlinkissue40094 messages
2020-04-01 09:40:38eryksuncreate