Eryk Sun <[email protected]> added the comment:
> I'm not actually sure what the proposal here is. Are we suggesting
> that all Python's means of terminating a process should use the
> same exit code?
That's how I read it, but I don't agree if it means always pretending that a
process was killed by a SIGTERM POSIX signal. That's fighting an uphill battle
against the platform and its conventions.
I singled out the case where multiprocessing tries to pretend that Windows has
Unix signals. It documents that `exitcode` will be negative if terminated by a
signal. It doesn't qualify that this is only in Unix.
exitcode
The child’s exit code. This will be None if the process has not
yet terminated. A negative value -N indicates that the child
was terminated by signal N.
A negative exit code in Windows (i.e. 0x8000_0000 and above) has many possible
meanings. Generally it indicates an abnormal error of some sort that terminated
the process, and generally the code is an NTSTATUS or HRESULT value, such as
STATUS_CONTROL_C_EXIT or E_FAIL (0x8000_4005). However, there isn't a
convention to use an NTSTATUS or HRESULT error code when manually terminating a
process. Instead, the convention is to use EXIT_FAILURE (1).
multiprocessing pretends that terminate() is implemented with a SIGTERM signal.
To do so, it terminates with an exit code that's just above the system 16-bit
range:
TERMINATE = 0x10000
def terminate(self):
if self.returncode is None:
try:
_winapi.TerminateProcess(int(self._handle), TERMINATE)
except OSError:
if self.wait(timeout=1.0) is None:
raise
and maps this code to -signal.SIGTERM:
def wait(self, timeout=None):
if self.returncode is None:
if timeout is None:
msecs = _winapi.INFINITE
else:
msecs = max(0, int(timeout * 1000 + 0.5))
res = _winapi.WaitForSingleObject(int(self._handle), msecs)
if res == _winapi.WAIT_OBJECT_0:
code = _winapi.GetExitCodeProcess(self._handle)
if code == TERMINATE:
code = -signal.SIGTERM
self.returncode = code
return self.returncode
I don't know why it doesn't simply use -SIGTERM instead of involving the
intermediate error code.
It's apparently trying to close a loop for scripts that call terminate() and
look for this case, or for logging, but the platform convention in Windows
doesn't allow distinguishing when a process was forcibly terminated. We don't
know whether an exit status of 1 means the process failed internally or was
forcibly terminated by another tool. So we can't rely on the exit code in
Windows in the same way that it can be relied on in POSIX. All we know is that
the process failed. Terminating with an exit code of 15 or -15 in some cases
does nothing to solve the problem in general.
----------
title: Inconsistent returncode/exitcode for terminated child processes on
Windows -> Inconsistent exitcode for terminated child processes on Windows
versions: +Python 3.10 -Python 3.7
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue31863>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com