C++线程中调用 std::terminate 时程序返回代码

C++ program return code when std::terminate is called in thread

本文关键字:程序 返回 代码 terminate C++ 调用 std 线程      更新时间:2023-10-16

我有一个程序,它使用std::thread对象并发执行工作。我正在从 bash 脚本调用该程序,如果程序没有以 EXIT_SUCCESS 终止,我想停止脚本。在以下情况下,我遇到了一个相当不直观的行为:其中一个线程抛出异常(因此调用std::terminate(,导致程序完全终止。但是,程序的返回代码是EXIT_SUCCESS的(而不是我期望的一些错误代码(。为什么?

我知道在许多情况下使用std::thread不是一个聪明的主意,我计划转向std::async(或类似(,但目前,我对快速解决方案感兴趣。

好吧,认为我很愚蠢。程序正确地返回了一个错误代码,但是当我将输出(它写入大量日志(tee时,存储在$?中的返回代码可能是tee之一,它退出而不会失败。

[编辑] 我现在正在使用PIPESTATUS来获取正确的退出代码。

正如理查德·克里滕在评论中指出的那样std::terminate()std::abort(),但这还不是全部。

C++提供了相当多的机制来控制这种情况。我可以建议如下:

使用以下std::set_terminate()注册您自己的处理程序以调用std::terminate()

#include <iostream>
#include <cstdlib>
#include <exception>
int main()
{
    std::set_terminate
    ( []()
      { 
        std::cout << "Unhandled exceptionn";
        std::exit(EXIT_FAILURE);
      }
    );
    throw 1;
}

调用std::exit()会导致程序正常终止,并执行一些清理步骤。

另一种选择是注册SIGABORT处理程序并使用所需的退出代码退出程序。但在这种情况下,不会进行资源清理。

C++11 具有允许在线程之间传输异常的exception_ptr类型。因此,如果要处理异常,可以考虑以下方法。

#include <iostream>
#include<thread>
#include<exception>
#include<stdexcept>
static std::exception_ptr eptr = nullptr;
void foo()
{
    try
    {
        ....
        throw std::runtime_error("Bla bla"); // put your exception instead of runtime_error
    }
    catch(...)
    {
        eptr = std::current_exception();
    }
}
int main(int argc, char **argv)
{
    std::thread t(foo);
    t.join();
    if (eptr)
    {
        try
        {
            std::rethrow_exception(eptr);
        }
        catch(const std::exception &ex)
        {
            std::cerr << "Thread exited: " << ex.what() << "n";
            return EXIT_FAILURE;
        }
    }
    return EXIT_SUCCESS;
}

此方法可确保程序在线程引发异常时以状态EXIT_FAILURE退出。