C++:如何为任意函数调用实现超时?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/879896/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++: How to implement a timeout for an arbitrary function call?
提问by Frank
I need to call a library function that sometimes won't terminate within a given time, unfortunately. Is there a way to call the function but abort it if it doesn't terminate within n
seconds?
不幸的是,我需要调用一个有时不会在给定时间内终止的库函数。有没有办法调用该函数但如果它没有在n
几秒钟内终止就中止它?
I cannot modify the function, so I cannot put the abort condition into it directly. I have to add a timeout to the function externally.
我无法修改该函数,因此无法直接将中止条件放入其中。我必须在外部向函数添加超时。
Is it maybe a possible solution to start it as a (boost) thread, which I can then terminate after a certain time? Would something like that work? I actually believe the function is notthread-safe, but that wouldn't matter if I run it as the onlysingle thread, right? Are there other (better) solutions?
将它作为(增强)线程启动,然后我可以在一段时间后终止它可能是一个可能的解决方案吗?这样的事情会奏效吗?我实际上认为该函数不是线程安全的,但是如果我将它作为唯一的单线程运行,那也没关系,对吗?还有其他(更好的)解决方案吗?
采纳答案by Ben Straub
You could spawn a boost::thread
to call the API:
您可以生成一个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 doesn't allow you to kill the worker thread, though. In this example, it's just orphaned.
但是,Boost 不允许您杀死工作线程。在这个例子中,它只是孤立的。
You'll have to be careful about what that API call does, because it may never release resources it's acquired.
您必须小心该 API 调用的作用,因为它可能永远不会释放它获取的资源。
回答by An???drew
I think the only safe way to accomplish this would be to spawn a separate sandboxprocess that calls the library function as a proxy to your application. You'll need to implement some type of IPC between your application and the proxy. Implementing a timeout on reading the IPC reply is then fairly trivial. If the read fails due to timeout, you can then safely terminate the proxy without risking the health of your application.
我认为实现这一点的唯一安全方法是生成一个单独的沙箱进程,该进程调用库函数作为应用程序的代理。您需要在应用程序和代理之间实现某种类型的 IPC。在读取 IPC 回复时实现超时是相当简单的。如果读取因超时而失败,您可以安全地终止代理,而不会危及应用程序的健康。
回答by Doug T.
What you are talking about is typically called a "watchdog" system. The watchdog is typically a second thread which checks on the status of all the other threads. The watchdog typically is setup to run periodically. If no response has been received from the other threads, the watchdog can notify the user, or even kill the offending thread if its possible to do so safely (depends on your application).
您所谈论的通常称为“看门狗”系统。看门狗通常是第二个线程,它检查所有其他线程的状态。看门狗通常设置为定期运行。如果没有收到来自其他线程的响应,看门狗可以通知用户,甚至在可能安全的情况下杀死有问题的线程(取决于您的应用程序)。
回答by Mykola Golubyev
The problem with threads is that some resources you won't be able to free after thread termination. If you don't acquire resources which you have to release then go with threads.
线程的问题在于某些资源在线程终止后将无法释放。如果您不获取必须释放的资源,请使用线程。
回答by Bruno Martinez
Boost.Test's execution_monitor does what you want:
Boost.Test 的 execution_monitor 做你想要的:
回答by peterchen
The problem is that with an in-process solution without support from the functionyou end up with potentially invalid state.
问题在于,如果使用没有函数支持的进程内解决方案,您最终会遇到潜在的无效状态。
Example: When you terminate the thread while a memory allocation is taking place, your process heap may be corrupted.
示例:当您在内存分配过程中终止线程时,您的进程堆可能已损坏。
So you might terminate the call, but then you also have to terminate the process. In many cases, the chances for destructive side effects are small, but I wouldn't bet my computation on that.
所以你可以终止调用,但你也必须终止进程。在许多情况下,发生破坏性副作用的可能性很小,但我不会把我的计算押在这一点上。
You can, as Ben Straub suggests, just orphan the thread: put it on lowest priority and let it run for infinity. That is of course only a limited solution: if the thread consumes ressources (likely), they will slow down the system, also there's a limit on threads per process (usually due to address space for thread stack).
正如 Ben Straub 建议的那样,您可以将线程孤立起来:将其置于最低优先级并让它无限运行。这当然只是一个有限的解决方案:如果线程消耗资源(可能),它们会减慢系统速度,而且每个进程的线程数也有限制(通常是由于线程堆栈的地址空间)。
Generally, I'd prefer the external process solution. A simple pattern is this:
Write input data to a file, start the external process with the file as argument. The external process writes progress (if any) to a disk file that can be monitored, and may even allow the process to resume from where it started. Results are written to disk, and the parent process can read them in.
通常,我更喜欢外部流程解决方案。一个简单的模式是:
将输入数据写入文件,以文件作为参数启动外部进程。外部进程将进程(如果有)写入可监控的磁盘文件,甚至可能允许进程从它开始的地方恢复。结果写入磁盘,父进程可以读入。
When you terminate the process, you still have to deal with synchronizing access to external ressources (like files), and how to deal with abandoned mutices, half-written files etc. But it's generally THE way to a robust solution.
当您终止进程时,您仍然需要处理对外部资源(如文件)的同步访问,以及如何处理废弃的 mutices、写到一半的文件等。但这通常是获得强大解决方案的方法。
回答by jpinto3912
Go with an Orphan process, launch it and time its execution. If it runs out of time, invoke the OS to kill it.
使用孤儿进程,启动它并为其执行计时。如果超时,请调用操作系统将其终止。
How to avoid race conds. on this pattern:
如何避免比赛条件。在这个模式上:
create a file to store in args (of course, everything is passed on as VALs). The orphan process is only allowed to read data from this file.
The orphan processes input data, creates an output file with result values and closes it.
Only when everything is done, orphan deletes the input file, a fact that signals the master process that work was done.
创建一个文件以存储在 args 中(当然,所有内容都作为 VAL 传递)。孤儿进程只允许从这个文件中读取数据。
孤儿处理输入数据,创建一个带有结果值的输出文件并关闭它。
只有当一切都完成后,孤儿才会删除输入文件,这一事实向主进程发出工作已完成的信号。
This avoids reading half-written files problem, since the master first notices absense of input file, opens for read the output file, which is surely completed (because was closed prior to deleting input, and OS call stacks are sequential).
这避免了读半写文件的问题,因为master首先注意到输入文件缺失,打开读取输出文件,这肯定完成(因为在删除输入之前关闭,并且操作系统调用堆栈是顺序的)。
回答by robguima
"I need to call a library function that sometimes won't terminate within a given time, unfortunately. Is there a way to call the function but abort it if it doesn't terminate within n seconds?"
“不幸的是,我需要调用一个有时不会在给定时间内终止的库函数。有没有办法调用该函数但如果它在 n 秒内没有终止就中止它?”
The short answer is no. That's usually trouble... The call itself must terminate at some time (implementing its own timeout), but blocking calls are usually trouble (e.g. gethostbyname()) because then it's up to their (or system) timeout, not yours.
最简洁的答案是不。这通常很麻烦...调用本身必须在某个时间终止(实现自己的超时),但阻塞调用通常很麻烦(例如 gethostbyname()),因为这取决于他们(或系统)超时,而不是您的超时。
So, whenever possible try to make the code running in the thread exit cleanly when necessary--the code itself must detect and handle the error. It can send a message and/or set statuses so that the main (or aother) thread knows what went on.
因此,只要有可能,就尽量让线程中运行的代码在必要时干净地退出——代码本身必须检测并处理错误。它可以发送消息和/或设置状态,以便主(或另一个)线程知道发生了什么。
Personal preference, in highly available systems, I like my threads spinning often (no busy-locking though) with specific timeouts, calling non-blocking functions, and with precise exit conditions in place. A global or thread-specific 'done' variable does the trick for a clean exit.
个人偏好,在高可用系统中,我喜欢我的线程经常旋转(尽管没有忙锁定),具有特定的超时、调用非阻塞函数和精确的退出条件。全局或线程特定的“完成”变量可以实现干净退出。
回答by lothar
What you need is a thread and a Future Objectthat can hold the result from the function call.
您需要的是一个线程和一个可以保存函数调用结果的Future 对象。
For an example using boost see here.
有关使用 boost 的示例,请参见此处。
You would need to check the future after the timeout and if it is not set, act accordingly.
您需要在超时后检查未来,如果未设置,请采取相应措施。