1

Lets say we have block of code, we just cant modify it, but we want to break it, exit this piece of code when it runs too long (x miliseconds)

Pseudo code

Throw exception after (500ms) {
    auto result = Do some risky job, for example test string by regex with catastrophic backtracking risk.
}
catch ( Exception e ) {
    //... 
}

Every thing has to be still in the same thread.

Is it possible with c++11 or with some other standard?

ElSajko
  • 1,612
  • 3
  • 17
  • 37

2 Answers2

4

In general, C++ does not have a way to induce an exception to be thrown in code without having code that throws an exception in the code, or in code that code calls.

You could embed an ASL, a scripting language, or a separate process. All 3 could be designed to be interrupted (processes, for example, can be killed).

Boost has interruptable threads. How it works is that it has hooks in the boost synchronization primitives (mutexes etc), so when you interact with them it checks if your thread has been told to halt. If so, it then throws an exception.

An easy, partial solution is to

std::vector<std::future<R()>> futures;
futures.push_back( std::async( std::launch::async, []()->R{ /* code */ ) );
using std::chrono::literals;
if (futures.back().wait_for(500ms)==std::future_status::ready) {
  auto r = futures.back().get();
  futures.pop_back();
  clear_ready_futures(futures); // wait for 0ms and if so, discard and destroy
  return r;
}
// failed case

here our futures stores the defunct futures (threads, in effect). clear_ready_futures cleans any old ones that have finished.

Tasks that have started will still run to completion, stealing cpu, but the calling code does not have to wait for them.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • If it happens a lot, should I consider keeping one thread and just send jobs to him? instead of creating new one each time I have a job to be done? – ElSajko Nov 01 '16 at 11:30
  • And another question. May it slow down the code significantly? the code that normally would be without timeouting. – ElSajko Nov 01 '16 at 11:32
  • Sure a job queue and thread pool is easy to write (many can be found on SO). Significant depends on what is significant: ns, ms, s? Really, measure. – Yakk - Adam Nevraumont Nov 01 '16 at 12:10
  • it seems to still wait for code execution, even if timeout is 2000 ms: http://pastebin.com/Jm8v8d9y – ElSajko Nov 01 '16 at 12:12
  • is there some way to stop running a job after timeout? – ElSajko Nov 01 '16 at 12:19
  • @elsal You must persist the vector. When it is destroyed everything waits. This does not help you stop the job, it just lets you do something else while it runs. – Yakk - Adam Nevraumont Nov 01 '16 at 12:22
  • but when catastrophic backtracking happens, it tooks minutes of executing eating whole cpu (ask google why they didn't fix it in V8 Regex) so waiting for the end even in background even if it non-blocks main thread isn't a way to deal with a subject. – ElSajko Nov 01 '16 at 12:37
  • @ElSajko Yes, it will keep running. Consider not using that library, or using that library in a separate process (where you actually can kill it... usually). When you look at a problem and say "I could solve this with regular expressions", you now have 2 problems: the original problem, and the fact you are using regular expressions. Sucks to be you. – Yakk - Adam Nevraumont Nov 01 '16 at 14:24
2

FreeBSD (as well as all other linux types) have "SigAlarm": Reference here

This will allow you to set up a timer; and when the event is triggered, your current code is interrupted, and signal handler called, setup by your previous call to signal

This will allow you to set a flag, which your ohh so very risky thread can check against; and then throw if required.

It won't allow you to raise exceptions directly in the way you want, but it will allow you to keep the application single threaded.

UKMonkey
  • 6,941
  • 3
  • 21
  • 30
  • Actually you might be even able to throw when using setjmp/longjmp with the signal handler. I used that once to translate signals to C++ exceptions. – EmDroid Oct 31 '16 at 16:47
  • Example of a longjump [here](https://www.gnu.org/software/libc/manual/html_node/Longjmp-in-Handler.html#Longjmp-in-Handler) – UKMonkey Oct 31 '16 at 16:51
  • setjmp/longjmp while there are RAII objects in automatic storage is not a good idea. – Yakk - Adam Nevraumont Oct 31 '16 at 20:04
  • @Yakk to be honest, not using another thread for this concept isn't a good idea, but interrupts are the only way to do this in a single threaded way. – UKMonkey Nov 01 '16 at 10:06
  • @ukmonkey Yes, but flags at least do not break the world. setjmp/longjmp does, unkess you are using them to have stackful coroutines or somesuch, which is not the case here. – Yakk - Adam Nevraumont Nov 01 '16 at 12:09