在处理异常后阻止线程在分离时调用std :: terminate()

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在处理异常后阻止线程在分离时调用std :: terminate()相关的知识,希望对你有一定的参考价值。

我有自己的线程类,旨在帮助安全地管理异常。它看起来像这样:(为简单起见跳过其他构造函数和互斥体)

class ExceptThread
    : public std::thread {
public:
    template<typename Func, typename... Args>
    ExceptThread(Func&& f, Args&&... args)
        : std::thread([] (Args&&... args) {
        try {
            return f(args...);
        } catch(...) {
            exc = std::current_exception();
        }
    }, args...) { }
    // skipped other constructors etc.
    //...    
    void check() { 
        if(exc) { 
            std::exception_ptr tmp = exc; 
            exc = nullptr; 
            std::rethrow_exception(tmp); 
        } 
    }

private:
    std::exception_ptr exc;
};

这个类意味着像:

ExceptThread et([] { std::this_thread::sleep_for(5s); throw std::runtime_error("Ugly exception"); });

try {
    while(/*...*/) {
        // main loop
        et.check();
    }
} catch(std::exception& e) {
    // do sth
}

问题:

当线程抛出异常时它会被卡在catch(...)并保存到exc,一切都很好。但是当执行进一步调用时,std::terminate被调用就像异常没被捕获一样。我还尝试在捕获异常后暂停子线程(例如Sleep(INFINITE)),但在主线程中的堆栈展开期间在std::terminate()中分离线程时调用std::thread::~thread()。如何防止系统这样做?

平台:MSVC

类似:How can I propagate exceptions between threads?

答案

你必须在破坏之前显式地加入一个线程,这有助于防止潜在的死锁/崩溃,当你在销毁之前忘记中断线程时(在我使用的每个实现中都在std :: terminate消息中说明) 。

以上是关于在处理异常后阻止线程在分离时调用std :: terminate()的主要内容,如果未能解决你的问题,请参考以下文章

分离的 std::thread 终止后是不是需要删除?

父线程离开其块后分离的 std::thread 的情况

JAVA 之 UNCAUGHTEXCEPTIONHANDLER异常处理机制

JAVA 之 UNCAUGHTEXCEPTIONHANDLER异常处理机制

如果在生成 std​​::thread 后引发异常,则不会捕获异常

ExecutorService 使用 invokeAll 和超时异常后可调用线程上的超时未终止