如何获取可能意外终止的扭曲生成进程的退出代码?
How can I get exit code of a twisted spawn process which may be terminated unexpected?
我正在使用 twisted 生成本地进程,该进程可能会在某些情况下终止。
我有一个自定义的反应堆 twisted.internet.protocol.ProcessProtocol
class。如果本地进程突然终止,我无法在 processEnded
中获取 return 值。 exitCode
设置为 None
。
一个mcv例子是这样的:
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()
并且 throw_exception
可执行文件可以编译自:
#include <iostream>
int main() {
throw std::runtime_error("some exception");
return 0;
}
执行 python 示例将打印
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
如果 shell 中的 运行,则 C++ 示例的 return 值为 134,这意味着 SIGABRT
(6) 已发送。 (我还测试了发送 SIGINT
以终止但仍然没有退出代码。)
如何在ProcessProtocal
实例中获取它?还是不可能?
在您的示例中,134 是 "wait status"(或者,在手册页中,是 "wstatus")。它编码了一些关于运行-状态转换的信息,该过程正在wait()
进行。
可能的转换是:
- 退出代码(即调用
exit(2)
)
- 被信号杀死
- 是否生成核心转储
- 已停止(例如被
SIGSTOP
)
- 未停止(例如
SIGCONT
)
POSIX提供了从等待状态中提取细节的宏:WIFEXITED
、WIFSIGNALED
、WTERMSIG
、WEXITSTATUS
等
Python 通过 os
模块公开这些:os.WIFEXITED
,等等
os.WIFEXITED(134)
的计算结果为 False
。 os.WIFSIGNALED(134)
的计算结果为真,os.WTERMSIG(134)
的计算结果为 6
。
ProcessDone
和 ProcessTerminated
使用这些宏来提取信息并以稍微更有用的形式呈现它 - exitCode
和 signal
属性。
但是,POSIX 没有提供一种方法来实现 other 方式。没有标准的 API 来构造一个 "wait status" 代表,比方说,"the process was killed by signal 6".
幸运的是,部分是因为没有办法倒退,Twisted 将异常的原始等待状态保留为 status
属性。如果您检查传递给 ProcessProtocol
的 Failure
中包含的异常的属性,您应该找到您正在寻找的等待状态。
我正在使用 twisted 生成本地进程,该进程可能会在某些情况下终止。
我有一个自定义的反应堆 twisted.internet.protocol.ProcessProtocol
class。如果本地进程突然终止,我无法在 processEnded
中获取 return 值。 exitCode
设置为 None
。
一个mcv例子是这样的:
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()
并且 throw_exception
可执行文件可以编译自:
#include <iostream>
int main() {
throw std::runtime_error("some exception");
return 0;
}
执行 python 示例将打印
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
如果 shell 中的 运行,则 C++ 示例的 return 值为 134,这意味着 SIGABRT
(6) 已发送。 (我还测试了发送 SIGINT
以终止但仍然没有退出代码。)
如何在ProcessProtocal
实例中获取它?还是不可能?
在您的示例中,134 是 "wait status"(或者,在手册页中,是 "wstatus")。它编码了一些关于运行-状态转换的信息,该过程正在wait()
进行。
可能的转换是:
- 退出代码(即调用
exit(2)
) - 被信号杀死
- 是否生成核心转储
- 已停止(例如被
SIGSTOP
) - 未停止(例如
SIGCONT
)
POSIX提供了从等待状态中提取细节的宏:WIFEXITED
、WIFSIGNALED
、WTERMSIG
、WEXITSTATUS
等
Python 通过 os
模块公开这些:os.WIFEXITED
,等等
os.WIFEXITED(134)
的计算结果为 False
。 os.WIFSIGNALED(134)
的计算结果为真,os.WTERMSIG(134)
的计算结果为 6
。
ProcessDone
和 ProcessTerminated
使用这些宏来提取信息并以稍微更有用的形式呈现它 - exitCode
和 signal
属性。
POSIX 没有提供一种方法来实现 other 方式。没有标准的 API 来构造一个 "wait status" 代表,比方说,"the process was killed by signal 6".
幸运的是,部分是因为没有办法倒退,Twisted 将异常的原始等待状态保留为 status
属性。如果您检查传递给 ProcessProtocol
的 Failure
中包含的异常的属性,您应该找到您正在寻找的等待状态。