I'm using twisted to spawn a local process, which may be terminated in some condition.
I have a custom twisted.internet.protocol.ProcessProtocol
class for the reactor. If the local process abruptly terminated, I can't get the return value in processEnded
. The exitCode
is set to None
.
A mcv example is like this:
from twisted.internet import error,protocol,reactor
class MyPP(protocol.ProcessProtocol):
def processEnded(self, reason):
if reason.check(error.ProcessTerminated):
err_info = "wrong termination: %s; exitCode: %s; signal: %s" % \
(reason, reason.value.exitCode, reason.value.signal)
print(err_info)
else:
print("processEnded, status %d" % (reason.value.exitCode,))
print("quitting")
reactor.stop()
pp = MyPP()
reactor.spawnProcess(pp, "throw_exception", ["throw_exception"], {})
reactor.run()
And the throw_exception
executable could be compiled from:
#include <iostream>
int main() {
throw std::runtime_error("some exception");
return 0;
}
Execute the python example will print
wrong termination: [Failure instance: Traceback (failure with no frames): : A process has ended with a probable error condition: process ended by signal 6. ]; exitCode: None; signal: 6
The C++ example will have a return value of 134 if run in a shell, which means SIGABRT
(6) sent. (I've also tested sending SIGINT
to terminate and still getting no exit code.)
How can I get it in the ProcessProtocal
instance? Or it is impossible?
In your example, 134 is the "wait status" (or, in the man pages, the "wstatus"). It encodes a few pieces of information about a running-state-transition the process being wait()
on underwent.
The possible transitions are:
exit(2)
)SIGSTOP
)SIGCONT
)POSIX provides macros for extracting the details from the wait status: WIFEXITED
, WIFSIGNALED
, WTERMSIG
, WEXITSTATUS
, etc.
Python exposes these through the os
module: os.WIFEXITED
, etc.
os.WIFEXITED(134)
evaluates to False
. os.WIFSIGNALED(134)
evaluates to true and os.WTERMSIG(134)
evaluates to 6
.
ProcessDone
and ProcessTerminated
use these macros to extract the information and present it in a slightly more useful form - the exitCode
and signal
attributes.
POSIX doesn't provide a way to go the other way, though. There's no standard API for constructing a "wait status" representing, say, "the process was killed by signal 6".
Fortunately, partially because there's no way to go backwards, Twisted preserves the original wait status on the exception as the status
attribute. If you check that attribute on the exception wrapped in the Failure
passed to your ProcessProtocol
, you should find the wait status you're looking for.