无法从Boost子进程获取分段故障退出代码 [英] Can't get segmentation fault exit code from boost child process

查看:309
本文介绍了无法从Boost子进程获取分段故障退出代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当子进程由于分段违规而被杀死或者除数为零或任何其他终止信号时,我试图获取子进程的退出代码(使用boost :: process和boost :: asio).退出代码和错误代码始终返回0并成功.

I am trying to get the exit code of a child process (using boost::process and boost::asio) when that child process is killed due to a segmentation violation or divide be zero or any other kill signal. The exit code and error code always return with 0 and success.

我正在使用g ++ 4.8.5和boost 1.66在CentOS 7上运行它

I am running this on CentOS 7 using g++ 4.8.5 and boost 1.66

如果我在子进程中运行相同的代码,而该子进程仅返回一个非零的退出代码,则它会成功返回该退出代码.

If I run the same code with a child process that simply returns a non-zero exit code it successfully returns that exit code.

#include <iostream>
#include <boost/process.hpp>
#include <boost/asio/io_service.hpp>

namespace bp = boost::process;
using namespace std;

int main (int argc, char** argv)
{
   string exe = "./crashes";

   vector<string> data;
   boost::asio::io_service ios;

   int exit_code;
   error_code ec;
   future<string> ostr;

   bp::child c(exe,
               (bp::std_out & bp::std_err) > ostr,
               ios,
               bp::on_exit=[&exit_code, &ec](int exit, const error_code& ecin)
                                             {exit_code = exit; ec = ecin;});

   ios.run();

   cout << "Exit Code = " << exit_code << endl;
   cout << "Error Code = " << ec.message() << endl;
   cout << "child stdin & stderr:\n";
   cout << ostr.get() << endl;
   return exit_code;
}

和崩溃代码

int main (int argc, char** argv)
{
   int* y = 0;
   int c = *y;
}

结果显示退出代码为0和成功错误代码

The results show a 0 exit code and Success error_code

Exit Code = 0
Error Code = Success
child stdin & stderr:

单独运行崩溃可执行文件将返回139的退出代码

running the crashes executable alone returns an exit code of 139

bash-4.2$ ./crashes 
Segmentation fault (core dumped)
bash-4.2$ echo $?
139

推荐答案

进程终止和退出代码的详细信息取决于平台.

The details of process termination and exit codes are platform dependent.

增强处理过程以解决默认接口中的差异:调用on_exit处理程序时,其退出状态的结果为boost::process::detail::posix::eval_exit_status(),这意味着:

Boost process papers over the differences in the default interface: your on_exit handler is called with the result of boost::process::detail::posix::eval_exit_status() of the exit status, which means:

inline int eval_exit_status(int code)
{
    if (WIFEXITED(code))
    {
        return WEXITSTATUS(code);
    }
    else if (WIFSIGNALED(code))
    {
        return WTERMSIG(code);
    }
    else
    {
        return code;
    }
}

因此,您会得到退出代码11",表示段错误...如果您想真正知道,可以查看native_exit_code()

So, you get "exit-code 11" meaning segfault... If you want to actually know, you can look at native_exit_code()

bp::on_exit = [&result, &c](int /*ignored*/, const std::error_code &ec) {
    auto exit_status = c.native_exit_code();
    result.exit_code = boost::make_optional(WIFEXITED(exit_status), WEXITSTATUS(exit_status));
    result.signal    = boost::make_optional(WIFSIGNALED(exit_status), WTERMSIG(exit_status));
    result.ec = ec;
}

现在,这假设对结果变量进行了一些更改.完整列表:

Now this assumes some changes to the result variables. Full listing:

#include <boost/asio/io_service.hpp>
#include <boost/process.hpp>
#include <iostream>

namespace bp = boost::process;

int main(int argc, char**) {
    std::string exe = argc>1? "./ltua" : "./crashes";

    boost::asio::io_service ios;

    struct {
        boost::optional<int> exit_code;
        boost::optional<int> signal;
        std::error_code ec{};
    } result;

    std::future<std::string> ostr;

    bp::group g;
    bp::child c(exe, g, (bp::std_out & bp::std_err) > ostr, ios,
        bp::on_exit = [&result, &c](int /*ignored*/, const std::error_code &ec) {
            auto exit_status = c.native_exit_code();
            result.exit_code = boost::make_optional(WIFEXITED(exit_status), WEXITSTATUS(exit_status));
            result.signal    = boost::make_optional(WIFSIGNALED(exit_status), WTERMSIG(exit_status));
            result.ec = ec;
        });

    //g.wait();
    ios.run();

    if (result.exit_code) {
        std::cout << "Exited with " << *result.exit_code << std::endl;
    }
    if (result.signal) {
        std::cout << "Signaled with sginal #" << *result.signal << ", aka " << ::strsignal(*result.signal) <<  std::endl;
    }

    std::cout << "Error Code = " << result.ec.message() << std::endl;
    std::cout << "child stdin & stderr:\n";
    std::cout << ostr.get() << std::endl;
    return result.exit_code? *result.exit_code : 255;
}

输出

ltua.cpp一起运行时:

#include <iostream>
int main() {
    std::cout << "so  long"   << std::end;
    std::cerr << "and thanks" << std::end;
    std::cout << "for all"    << std::end;
    std::cerr << "the fish"   << std::end;
    return 42;
}

打印

Exited with 42
Error Code = Success
child stdin & stderr:
so  long
and thanks
for all
the fish

并使用crashes.cpp:

int main() {
    int *y = 0;
    int c = *y;
}

打印

Signaled with sginal #11, aka Segmentation fault
Error Code = Success
child stdin & stderr:

这篇关于无法从Boost子进程获取分段故障退出代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆