2009-05-18 220 views
25

不幸的是,我需要调用一个库函数,它有时不会在给定的时间内终止。有没有办法调用该函数,但如果它不在n秒内终止,则中止它?C++:如何实现任意函数调用的超时?

我不能修改函数,所以我不能直接放入中止条件。我必须添加一个超时功能外部

这可能是一个可能的解决方案,将其作为(boost)线程启动,然后我可以在一段时间后终止?会有那样的工作吗?我其实是相信功能是不是线程安全,但是如果我将它作为只有单线程运行它并不重要,对吧?还有其他(更好的)解决方案吗?

+0

库函数是做什么的? – peterchen 2009-05-19 13:02:52

+0

Uuh,计算一些东西......科学计算实际上不会在某些条件下终止。 – Frank 2009-05-19 23:57:31

回答

18

你可以生成一个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 
} 

升压不允许你杀工作线程,虽然。在这个例子中,它只是孤儿。

您必须小心该API调用的功能,因为它可能永远不会释放它所获取的资源。

8

你在说什么通常称为“看门狗”系统。看门狗通常是第二个线程,用于检查所有其他线程的状态。看门狗通常设置为定期运行。如果没有收到来自其他线程的响应,那么看门狗可以通知用户,或者甚至在可能的情况下安全地取消违规线程(取决于您的应用程序)。

+4

根据库函数的作用,杀死没有响应的线程可能非常不安全。一种安全的方法是将任务分派到单独的过程。 – 2009-05-18 21:27:53

+0

如何开始这样一个单独的过程?我的应用程序可以传递一些数据(并返回一些结果数据)而不通过文件系统吗? – Frank 2009-05-18 21:48:43

+1

这是有点复杂,特定于平台 - 可能很容易成为一个单独的stackoverflow问题,我想。有几种方法可以在进程之间传递数据。这称为IPC(进程间通信),也是平台特定的。 – 2009-05-18 21:56:21

3

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

14

我认为完成此操作的唯一安全方法是产生一个独立的沙箱进程,该进程将库函数作为应用程序的代理进行调用。您需要在应用程序和代理之间实现某种类型的IPC。在阅读IPC回复时实现超时是相当平凡的。如果读取由于超时而失败,则可以安全地终止代理,而不会危及应用程序的健康。

1

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

对于使用boost的示例,请参见here

您需要在超时后检查未来,如果未设置,请按照相应的步骤操作。

3

的问题是,与进程解决方案不支持的功能你最终可能无效的状态。

示例:当内存分配发生时终止线程时,您的进程堆可能已损坏。

因此,您可能会终止通话,但您也必须终止处理。在很多情况下,破坏性副作用的可能性很小,但我不会在这方面打赌我的计算。

就像本·斯特劳布所说的,你可以孤立地把它放在最低优先级上,让它跑向无穷大。这当然只是一个有限的解决方案:如果线程消耗资源(可能),它们将减慢系统速度,并且每个进程的线程数也有限制(通常是由于线程堆栈的地址空间)。

通常,我更喜欢外部处理解决方案。一个简单的模式是这样的:
将输入数据写入文件,使用文件作为参数启动外部进程。外部进程将进程(如果有)写入可监控的磁盘文件,甚至可以允许进程从启动的位置恢复。结果被写入磁盘,并且父进程可以读取它们。

当您终止进程时,您仍然必须处理同步对外部资源(如文件)的访问,以及如何处理被遗弃的重复文件等。但它通常是一个强大的解决方案。

1

使用孤立进程,启动它并计时执行。如果耗尽时间,请调用操作系统来杀死它。

如何避免种族conds。在这种模式下:

  • 创建一个文件存储在参数(当然,一切都是作为VAL传递)。 孤儿进程只允许从这个文件读取数据。

  • 孤儿进程输入数据,创建一个结果值的输出文件并关闭它。

  • 只有当一切都完成,孤儿删除输入文件,这是一个事实,表明主进程工作已完成。

这避免了阅读半写入的文件的问题,由于主第一次注意到由于缺少输入文件,用于读取输出文件,该文件确实完成开(因为在之前删除输入关闭,操作系统调用堆栈是顺序的)。

1

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

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

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

个人喜好,在高度可用的系统中,我喜欢我的线程经常旋转(尽管没有忙锁定),具有特定的超时,调用非阻塞函数,并且具有精确的退出条件。全局或特定于线程的“完成”变量为干净退出提供了技巧。