我有一个程序,它创建使用std::thread
个对象同时执行工作。我从bash脚本调用程序,如果程序没有以EXIT_SUCCESS
终止,则想要停止脚本。在以下情况下,我遇到了一种非直观的行为:其中一个线程抛出异常(因此调用std::terminate
),导致程序完全终止。但是,程序的返回码是EXIT_SUCCESS
(而不是我期望的一些错误代码)。那是为什么?
我知道在许多情况下使用std::thread
并不是一个聪明的主意,我打算转移到std::async
(或类似),但此刻,我对a感兴趣快速解决这个问题。
答案 0 :(得分:1)
好吧,我觉得我很蠢。程序正确返回错误代码,但是当我将输出(它写入大量日志)传送到tee
时,存储在$?
中的返回码可能是tee
中的一个,退出而没有失败。
[编辑]我现在正在使用PIPESTATUS
来获取正确的退出代码。
答案 1 :(得分:1)
正如理查德·克里滕在评论std::terminate()
中提到std::abort()
所指出的那样,但并非全部。{/ p>
C ++提供了很多控制这种情况的机制。我可以建议的是:
为std::terminate()
的来电注册您自己的处理程序
#include <iostream>
#include <cstdlib>
#include <exception>
int main()
{
std::set_terminate
( []()
{
std::cout << "Unhandled exception\n";
std::exit(EXIT_FAILURE);
}
);
throw 1;
}
调用std::exit()
会导致程序正常终止并执行一些清理步骤。
另一种选择是注册SIGABORT
处理程序并使用所需的退出代码退出程序。但在这种情况下,没有资源清理。
答案 2 :(得分:0)
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
退出。