如何获得可能被意外终止的扭曲生成过程的退出代码?

时间:2017-02-15 04:51:11

标签: python twisted twisted.internet

我使用twisted来生成本地进程,可能会在某些情况下终止。

我有一个反应堆的自定义twisted.internet.protocol.ProcessProtocol类。如果本地进程突然终止,我无法在processEnded中获得返回值。 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示例将打印

  

错误终止:[失败实例:回溯(失败,没有   frames)::一个过程   以可能的错误条件结束:过程由信号6结束。   ]。 exitCode:无;信号:6

如果在shell中运行,C ++示例的返回值为134,这意味着发送了SIGABRT(6)。 (我还测试了发送SIGINT以终止并仍然没有退出代码。)

如何在ProcessProtocal实例中获取它?或者这是不可能的?

1 个答案:

答案 0 :(得分:1)

在您的示例中,134是“等待状态”(或在手册页中,“wstatus”)。它编码了一些有关正在进行wait()过程的运行状态转换的信息。

可能的转变是:

  • 退出代码(即名为exit(2)
  • 被信号杀死
  • 是否生成核心转储
  • 已停止(例如SIGSTOP
  • 未被停止(例如使用SIGCONT

POSIX提供用于从等待状态中提取详细信息的宏:WIFEXITEDWIFSIGNALEDWTERMSIGWEXITSTATUS等。

Python通过os模块公开这些内容:os.WIFEXITED等等。

os.WIFEXITED(134)评估为Falseos.WIFSIGNALED(134)评估为true,os.WTERMSIG(134)评估为6

ProcessDoneProcessTerminated使用这些宏来提取信息并以更有用的形式呈现 - exitCodesignal属性。

虽然POSIX没有提供一种方法来使用其他方式。没有用于构建“等待状态”的标准API,例如,“该过程被信号6杀死”。

幸运的是,部分因为没有办法倒退,Twisted会将异常的原始等待状态保留为status属性。如果您检查传递给Failure的{​​{1}}中包含的异常上的该属性,您应该找到您正在寻找的等待状态。