不幸的是,我需要调用有时不会在给定时间内终止的库函数。有没有办法调用该函数,但如果它没有在n
秒内终止,则中止它?
我无法修改该功能,所以我不能直接将中止条件放入其中。我必须在外部添加超时功能。
是否可能将解决方案作为(提升)线程启动,然后我可以在一段时间后终止它?会有类似的东西吗?我实际上认为该函数不是线程安全的,但如果我将它作为唯一的单线程运行则无关紧要,对吧?还有其他(更好的)解决方案吗?
答案 0 :(得分: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
}
但是,Boost不允许你杀死工作线程。在这个例子中,它只是孤立的。
你必须要小心API调用的作用,因为它可能永远不会释放它所获得的资源。
答案 1 :(得分:15)
我认为实现这一目标的唯一安全方法是生成一个单独的沙箱进程,该进程将库函数作为应用程序的代理调用。您需要在应用程序和代理之间实现某种类型的IPC。在读取IPC回复时实现超时非常简单。如果读取因超时而失败,则可以安全地终止代理,而不会危及应用程序的运行状况。
答案 2 :(得分:8)
你所说的通常被称为“看门狗”系统。监视程序通常是第二个线程,它检查所有其他线程的状态。看门狗通常设置为定期运行。如果没有收到来自其他线程的响应,监视程序可以通知用户,甚至可以安全地杀死有问题的线程(取决于你的应用程序)。
答案 3 :(得分:3)
线程的问题是在线程终止后你将无法释放一些资源。如果您没有获得必须释放的资源,那么请使用线程。
答案 4 :(得分:3)
Boost.Test的execution_monitor做你想做的事:
答案 5 :(得分:3)
问题在于,如果没有函数支持的进程内解决方案 ,最终可能会出现无效状态。
示例:在进行内存分配时终止线程时,您的进程堆可能已损坏。
因此您可以终止呼叫,但是您还必须终止该过程。在许多情况下,破坏性副作用的可能性很小,但我不打赌我的计算。
正如Ben Straub建议的那样,你可以孤立线程:把它放在最低优先级并让它运行无限。这当然只是一个有限的解决方案:如果线程消耗资源(可能),它们将减慢系统速度,每个进程的线程也有限制(通常是由于线程堆栈的地址空间)。
一般来说,我更喜欢外部流程解决方案。一个简单的模式是:
将输入数据写入文件,以文件作为参数启动外部进程。外部进程将进度(如果有)写入可以监视的磁盘文件,甚至可以允许进程从其开始的位置继续。结果将写入磁盘,父进程可以读取它们。
当你终止这个过程时,你仍然需要处理同步对外部资源(如文件)的访问,以及如何处理被遗弃的变种,半写文件等等。但它通常是一种强大的解决方案。 / p>
答案 6 :(得分:1)
答案 7 :(得分:1)
使用Orphan进程,启动它并计算执行时间。如果时间不够,请调用操作系统将其删除。
如何避免种族冲突。在这种模式上:
创建一个存储在args中的文件(当然,所有内容都作为VAL传递)。 孤儿进程只允许从该文件中读取数据。
孤儿处理输入数据,创建一个带有结果值的输出文件并将其关闭。
只有当一切都完成后,orphan才会删除输入文件,这表明主进程已完成工作。
这避免了读取半写文件的问题,因为主设备首先注意到输入文件的缺失,打开以读取输出文件,这肯定已经完成(因为在删除输入之前关闭,并且OS调用堆栈是顺序的)。
答案 8 :(得分:1)
“不幸的是,我需要调用一个有时不会在给定时间内终止的库函数。有没有办法调用函数,但是如果它在n秒内没有终止就会中止它?”
简短的回答是否定的。这通常是麻烦......调用本身必须在某个时间终止(实现自己的超时),但阻塞调用通常是麻烦(例如gethostbyname()),因为这取决于他们(或系统)的超时,而不是你的。
因此,只要有可能,尝试在必要时使代码在线程中运行干净 - 代码本身必须检测并处理错误。它可以发送消息和/或设置状态,以便主(或另一个)线程知道发生了什么。
个人偏好,在高度可用的系统中,我喜欢经常旋转的线程(没有忙碌锁定),具有特定的超时,调用非阻塞功能,以及准确的退出条件。一个全局或特定于线程的'done'变量可以实现干净的退出。