C++: How to Implement a Timeout for an Arbitrary Function Call

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

You could spawn a boost::thread to call the 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.

You'll have to be careful about what that API call does, because it may never release resources it's acquired.

ACE C++ - How do I implement timeout for a function call?

Put the function in a separate thread. If the thread hasn't exited within the timeout, then detach it and let it run to finish in the background without getting any result from it.

Note that this won't work if the function has side-effects (like writing to a file).

How to implement timeout for function in c++

You can create a separate thread to run the call itself, and wait on a condition variable back in your main thread which will be signalled by the thread doing the call to f once it returns. The trick is to wait on the condition variable with your 1s timeout, so that if the call takes longer than the timeout you will still wake up, know about it, and be able to throw the exception - all in the main thread. Here is the code (live demo here):

#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>

using namespace std::chrono_literals;

int f()
{
std::this_thread::sleep_for(10s); //change value here to less than 1 second to see Success
return 1;
}

int f_wrapper()
{
std::mutex m;
std::condition_variable cv;
int retValue;

std::thread t([&cv, &retValue]()
{
retValue = f();
cv.notify_one();
});

t.detach();

{
std::unique_lock<std::mutex> l(m);
if(cv.wait_for(l, 1s) == std::cv_status::timeout)
throw std::runtime_error("Timeout");
}

return retValue;
}

int main()
{
bool timedout = false;
try {
f_wrapper();
}
catch(std::runtime_error& e) {
std::cout << e.what() << std::endl;
timedout = true;
}

if(!timedout)
std::cout << "Success" << std::endl;

return 0;
}

Arbitrary function call with boost::lambda::bind?

would this work?

template <class T, class F>
T timeout(const F &bind, long sleep) {
T ret;
boost::thread thrd(boost::lambda::var(ret) = bind);
if(thrd.timed_join(boost::posix_time::milliseconds(sleep))) {
return ret;
}
else throw std::runtime_error("timeout");
}

How to implement a timed wait around a blocking call?

You could use sigaction(2) and alarm(2), which are both POSIX. You set a callback action for the timeout using sigaction, then you set a timer using alarm, then make your blocking call. The blocking call will be interrupted if it does not complete within your chosen timeout (in seconds; if you need finer granularity you can use setitimer(2)).

Note that signals in C are somewhat hairy, and there are fairly onerous restriction on what you can do in your signal handler.

This page is useful and fairly concise:
http://www.gnu.org/s/libc/manual/html_node/Setting-an-Alarm.html

How to set a timeout for MySQL query using C API

Okay, I found a solution.. Thanks to Will and PRR( my co-worker ).

I cannot start a new thread on each query, as this is a real-time application, that is supposed to process 1000+ messages per second..(anyway, thanks to R.. for the idea).

Also, it was not possible to terminate the connection through the library, nor to cancel/kill the query, as the problem was in the DB server..

And here's a brute-force solution, but still much better that _EXIT( FAILURE ): Here's the related question: "How to force closing socket on Linux?" - so, I just closed the socket using a system call.

Important NOTE: (thanks Will) - It turned out, that our MySQL library wrapper has s "fail-safe" flag, so that on closed socket (or other critical error), it tries to "solve" the problem, so it reopens the socket, by itself, in my case. So, I just turned off this option and everything is fine now - the execute is terminated because of an exception - this is the "softest" way to do this.

This should be done through another thread, of course - a timer, for example.

EDIT: The timeouts are really working for versions after 5.0.25. But, at least on RHEL4 and RHEL5, the timeouts are tripled for some reason! For example, if some of the timeouts is set to 20sec, the real timeout is ~60sec..

Also, another important thing is, that these timeouts(as any other options) MUST be set after mysql_init and before mysql_connect or mysql_real_connect.



Related Topics



Leave a reply



Submit