繁体   English   中英

C ++:如何实现任意函数调用的超时?

[英]C++: How to implement a timeout for an arbitrary function call?

不幸的是,我需要调用有时不会在给定时间内终止的库函数。 有没有办法调用该函数,但如果它不在n秒内终止就中止它?

我无法修改函数,所以我不能直接将中止条件放入其中。 我必须在外部为函数添加超时

它可能是一个可能的解决方案,将其作为(提升)线程启动,然后我可以在一段时间后终止它? 会有类似的东西吗? 我实际上认为该函数不是线程安全的,但如果我将它作为唯一的单线程运行则无关紧要,对吧? 还有其他(更好的)解决方案吗?

你可以产生一个boost::thread来调用API:

boost::thread api_caller(::api_function, arg1, arg2);
if (api_caller.timed_join(boost::posix_time::milliseconds(500)))
{
    // API call returned within 500ms
}
else
{
    // API call timed out
}

但是,Boost不允许你杀死工作线程。 在这个例子中,它只是孤儿。

你必须要小心API调用的作用,因为它可能永远不会释放它所获得的资源。

我认为实现这一目标的唯一安全方法是生成一个单独的沙箱进程,该进程将库函数作为应用程序的代理调用。 您需要在应用程序和代理之间实现某种类型的IPC。 在读取IPC回复时实现超时非常简单。 如果读取因超时而失败,则可以安全地终止代理,而不会危及应用程序的运行状况。

你所说的通常被称为“看门狗”系统。 监视程序通常是第二个线程,它检查所有其他线程的状态。 看门狗通常设置为定期运行。 如果没有从其他线程收到响应,则监视程序可以通知用户,或者如果可以安全地(取决于您的应用程序)可以杀死有问题的线程。

线程的问题是在线程终止后你将无法释放一些资源。 如果您没有获得必须释放的资源,那么请使用线程。

问题是, 如果没有函数支持的进程内解决方案您最终可能会出现无效状态。

示例:在进行内存分配时终止线程时,进程堆可能已损坏。

因此,您可以终止呼叫,但之后您还必须终止该过程。 在许多情况下,破坏性副作用的可能性很小,但我不打赌我的计算。

正如Ben Straub建议的那样,你可以孤立线程:把它放在最低优先级并让它运行无穷大。 这当然只是一个有限的解决方案:如果线程消耗资源(可能),它们将减慢系统速度,每个进程的线程也有限制(通常是由于线程堆栈的地址空间)。

通常,我更喜欢外部流程解决方案。 一个简单的模式是这样的:
将输入数据写入文件,以文件作为参数启动外部进程。 外部进程将进度(如果有)写入可以监视的磁盘文件,甚至可以允许进程从其开始的位置继续。 结果将写入磁盘,父进程可以读取它们。

当你终止进程时,你仍然需要处理同步对外部资源(如文件)的访问,以及如何处理被遗弃的mutices,半写文件等。但它通常是一种强大的解决方案。

“不幸的是,我需要调用有时不会在给定时间内终止的库函数。有没有办法调用函数,但如果它在n秒内没有终止就会中止它?”

最简洁的答案是不。 这通常是麻烦...调用本身必须在某个时间终止(实现自己的超时),但是阻塞调用通常是麻烦的(例如gethostbyname()),因为这取决于他们(或系统)超时,而不是你的。

因此,只要有可能,尝试在必要时使代码在线程中运行干净 - 代码本身必须检测并处理错误。 它可以发送消息和/或设置状态,以便主(或另一个)线程知道发生了什么。

个人偏好,在高度可用的系统中,我喜欢我的线程经常旋转(没有忙碌锁定),具有特定的超时,调用非阻塞功能,以及准确的退出条件。 一个全局或特定于线程的'done'变量可以实现干净的退出。

你需要的是一个线程和一个Future Object ,它可以保存函数调用的结果。

有关使用boost的示例,请参阅此处

您需要在超时后检查未来,如果未设置,则采取相应措施。

使用孤立进程,启动它并计算执行时间。 如果时间不够,请调用操作系统将其终止。

如何避免种族冲突。 在这种模式上:

  • 创建一个存储在args中的文件(当然,所有内容都作为VAL传递)。 孤立进程只允许从该文件中读取数据。

  • 孤立处理输入数据,创建带有结果值的输出文件并关闭它。

  • 只有当一切都完成后,orphan才会删除输入文件,这一事实表明主进程已完成工作。

这避免了读取半写文件的问题,因为主设备首先注意到输入文件的缺失,打开以读取输出文件,这肯定已经完成(因为在删除输入之前关闭,并且OS调用堆栈是顺序的)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM