Eryk Sun <[email protected]> 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 <[email protected]>
<https://bugs.python.org/issue40094>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com