首页 > 解决方案 > 如果线程在 C++ 中阻塞,则强制程序终止

问题描述

当一个类负责管理一个线程时,在确保线程及时完成后,在析构函数中加入该线程是一种常见的模式(参见示例here )。然而,这并不总是微不足道的,正如链接线程中所概述的那样,如果执行不正确,程序将永远不会终止。下面给出了一个重现这种情况的例子:

#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono_literals;

class Foo {
public:
    Foo() {
        mythread = std::thread([&](){
        int i = 0;
            while(running) {
                std::cout << "hi" << std::endl;
                if (i++ >= 2) {
                    // placeholder for e.g. a blocking condition variable
                    std::this_thread::sleep_for(1000h);
                }
                std::this_thread::sleep_for(500ms);
            }
        });
    }

    ~Foo() {
        running = false;
        mythread.join();
    }

private:
    std::thread mythread;
    bool running{true};
};

int main() {
    Foo bar;
    std::this_thread::sleep_for(1s);

    // enabling this line will block the termination
    //std::this_thread::sleep_for(2s);

    std::cout << "ending" << std::endl;
}

我正在寻找的是一种解决方案,如果发生这种情况,它会强制终止程序。当然,人们应该始终努力正确地完成线程,但是拥有这样的功能将作为最后的手段让您安心,特别是对于无法观察到的嵌入式系统,崩溃程序比阻塞程序更容易恢复和调试。

一个粗略的解决方案草案是在主线程的末尾启动一个线程,该线程休眠几秒钟,如果程序在那段时间之后还没有结束,则调用 std::terminate (理想情况下会报告相应的错误)。然而,我们有一个先有鸡还是先有蛋的问题,因为这个新线程当然会阻止程序及时结束。我将非常感谢任何想法。

编辑:该解决方案不应要求修改 Foo 类本身,以便它还涵盖例如外部库的未修改代码中的相应错误。理想情况下,它甚至会涵盖没有类认为负责在主要结束之前结束它们的线程(具有静态存储持续时间的类,甚至不再引用具有动态存储持续时间的对象),但如果没有深入的操作系统黑客攻击,这可能根本不可能或外部过程监视器。

标签: c++multithreading

解决方案


有几种解决方案:

  • 调查并解决根本问题(这是最好和正确的解决方案)

解决方法:

  • 您可以通过条件变量从线程通知退出。而且只有在它做之后join。如果 CVwait_for超时返回 - 杀死线程(不好的解决方案,还有另一个问题)。
  • 您可以创建监视线程,它将验证时间计数器。应用程序应不时重置计数器。如果监视线程在时间计数器中​​检测到过高的值,它会重新启动整个应用程序。
  • 将可疑代码移出您的应用程序以分离进程并通过 IPC 与其通信。如果出现问题 - 重新启动该应用程序(最好的解决方法)

推荐阅读