Eryk Sun <eryk...@gmail.com> added the comment:

> 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).

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue40094>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to