如何在C ++中的线程中正确处理永久挂起的第三方库调用?

时间:2014-09-13 08:30:52

标签: c++ multithreading c++11 boost-asio future

我有一个有图书馆的设备。它的一些功能最令人敬畏,在“偶尔挂起”的意义上。

我有一个使用此设备的程序。如果/何时挂起,我需要能够优雅地恢复并重置它。有问题的调用应该在几毫秒内返回,并且每秒循环调用很多次。

我的第一个问题是:当运行顽抗函数的线程挂起时,我该怎么办?即使我用中断点乱丢线程,也会发生这种情况:< / p>

boost::this_thread::interruption_point(); // irrelevant, in the past
deviceLibrary.thatFunction(); // <-- hangs here forever
boost::this_thread::interruption_point(); // never gets here!

我读到的关于该做什么的唯一一个词是修改功能本身,但出于各种原因这是不可能的 - 尤其是“这已经超出了我的技能范围”

我尝试使用C ++ 11期货进行异步启动:

// this was in a looping thread -- it does not work: wait_for sometimes never returns
std::future<void> future = std::async(std::launch::async, 
    [this] () { deviceLibrary.thatFunction(*data_ptr); }); 
if (future.wait_for(std::chrono::seconds(timeout)) == std::future_status::timeout) { 
    printf("no one will ever read this\n"); 
    deviceLibrary.reset(); // this would work if it ever got here
}

没有骰子,在那个或多个变化中。

我现在正在尝试boost::asio thread_group运行io_service::run()的多个工作线程。它非常有效,直到第二次超时。然后我的线程用完了,因为每个挂线都会占用我thread_group中的一个,它永远不会回来。

我的最新想法是致电work_threads.create_thread创建一个新线程来取代现在悬挂的线程。所以我的第二个问题是:如果这是一个可行的方法来解决这个问题,我应该如何应对缓慢积累的一组悬挂线程?我该如何删除它们?将它们留在那里可以吗?

顺便提一下,我应该提到实际上有deviceLibrary.thatFunction()的版本有超时。它没有。

我找到this answer但它是C#和Windows特定的,而this one似乎相关。但是我不太确定每秒产生数百个额外的进程(编辑:哦,对了;我可以放弃对一个或两个单独进程的所有调用。如果他们通信得很好并且我可以共享他们之间的设备。嗯...)

相关背景信息:我在Windows 7上使用MSVC 2013,但代码必须在Debian上与GCC 4.6交叉编译ARM。我的C ++知识水平是......好吧......如果看起来我错过了一些明显的东西,我可能就是。

谢谢!

3 个答案:

答案 0 :(得分:8)

如果您想要可靠地杀死某些不受控制的东西并且可能会挂起,请使用单独的过程。

虽然过程隔离一度被认为是非常严厉的,但今天Chrome这样的浏览器会在每个标签的基础上实现它。每个选项卡都有一个进程,GUI有一个进程,如果选项卡渲染消失,它就不会取消整个浏览器。

How can Google Chrome isolate tabs into separate processes while looking like a single application?

线程根本不是为让代码库保护自己免受不良行为库而设计的。流程是。

因此,定义您需要的服务,使用您的片状库将所有服务放在一个程序中,并使用主应用程序的进程间通信来与桥接器通信。如果桥梁由于剥落而超时或出现问题,请将其杀死并重新启动。

答案 1 :(得分:1)

我只会回答你的文字的这一部分: 当运行顽抗功能的线程挂起时,我该怎么办?

线程可以调用内联机器指令。 这些指令可能会清除中断标志。 这可能导致代码不可中断。 只要它不决定返回,你就不能强迫它返回。 您可能可以强制它死掉(例如,杀死包含该线程的进程),但是您无法强制返回代码。

我希望我的回答让您相信,建议使用桥接过程的答案实际上是您应该做的。

答案 2 :(得分:-3)

你要做的第一件事是确保它是错误的库。然后,您创建一个演示问题的最小示例(如果可能),并将错误报告和示例发送给库的开发人员。最后,你伸出手指等待。

你不做的是将你的手指放在你的耳朵里说“LALALALALA”,同时你把问题隐藏在层层背后,试图假装问题消失了。