c++ - 如果线程在 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 类本身,以便它还涵盖例如外部库的未修改代码中的相应错误。理想情况下,它甚至会涵盖没有类认为负责在主要结束之前结束它们的线程(具有静态存储持续时间的类,甚至不再引用具有动态存储持续时间的对象),但如果没有深入的操作系统黑客攻击,这可能根本不可能或外部过程监视器。
解决方案
有几种解决方案:
- 调查并解决根本问题(这是最好和正确的解决方案)
解决方法:
- 您可以通过条件变量从线程通知退出。而且只有在它做之后
join
。如果 CVwait_for
超时返回 - 杀死线程(不好的解决方案,还有另一个问题)。 - 您可以创建监视线程,它将验证时间计数器。应用程序应不时重置计数器。如果监视线程在时间计数器中检测到过高的值,它会重新启动整个应用程序。
- 将可疑代码移出您的应用程序以分离进程并通过 IPC 与其通信。如果出现问题 - 重新启动该应用程序(最好的解决方法)
推荐阅读
- python - 使用python使用FPDF导入字体时出现问题
- nginx - Kubernetes Ingress/nginx pod 特定值
- xml - XSD 架构:使元素 *List 可选
- r - 如何在 R 中使用 LDAvis 可视化种子 LDA 模型?
- python - 是否可以使用参数自动生成函数?
- ios - Unity-iPhone" 需要配置文件
- javascript - 未显示 svg 内的视频
- java - 无法再运行项目并出现错误:未设置“hibernate.dialect”时对 DialectResolutionInfo 的访问不能为空
- blazor - .Net 5 Blazor WASM 只想在表格列中显示部分字符串
- python - 在python中满足条件后读取下一行的方法