7

Say I have a function whose prototype looks like this, belonging to class container_class:

std::vector<int> container_class::func(int param);

The function may or may not cause an infinite loop on certain inputs; it is impossible to tell which inputs will cause a success and which will cause an infinite loop. The function is in a library of which I do not have the source of and cannot modify (this is a bug and will be fixed in the next release in a few months, but for now I need a way to work around it), so solutions which modify the function or class will not work.

I've tried isolating the function using std::async and std::future, and using a while loop to constantly check the state of the thread:

container_class c();

long start = get_current_time(); //get the current time in ms
auto future = std::async(&container_class::func, &c, 2);

while(future.wait_for(0ms) != std::future_status::ready) {
    if(get_current_time() - start > 1000) {
        //forcibly terminate future
    }

    sleep(2);
}

This code has many problems. One is that I can't forcibly terminate the std::future object (and the thread that it represents).

At the far extreme, if I can't find any other solution, I can isolate the function in its own executable, run it, and then check its state and terminate it appropriately. However, I would rather not do this.

How can I accomplish this? Is there a better way than what I'm doing right now?

ack
  • 1,181
  • 1
  • 17
  • 36
  • You might run this in a separate thread and then kill the thread. This might not be possible in the higher-level interface that futures are. – Martin Ueding Mar 26 '18 at 14:54
  • Possible duplicate of [Timeout for thread.join()](https://stackoverflow.com/questions/9948420/timeout-for-thread-join) – Severin Pappadeux Mar 26 '18 at 14:55
  • 1
    @SeverinPappadeux of course not. The question linked asks about timed waits, the question here asks about forceful termination. – SergeyA Mar 26 '18 at 14:58
  • 1
    @SeverinPappadeux I'm not sure if that would work since the OP is calling a library function which can't be modified. – NathanOliver Mar 26 '18 at 14:58
  • @SergeyA Huh?!? What do you think `future.wait_for()` is used for? Anyway, please check SECOND answer, it is clearly applicable to OP question – Severin Pappadeux Mar 26 '18 at 15:00
  • @NathanOliver I believe SECOND answer to the question is exactly what OP asking for – Severin Pappadeux Mar 26 '18 at 15:01
  • 1
    @SeverinPappadeux That still fails to explain how to end that thread the future is running is it is an infinite loop. – NathanOliver Mar 26 '18 at 15:01
  • 1
    @SeverinPappadeux I suggest you read both questions. Your duplicate is clearly inapplicable. – SergeyA Mar 26 '18 at 15:02
  • If you want something portable I think you will have to put this code in its own process instead of just a thread. – NathanOliver Mar 26 '18 at 15:03
  • 3
    @MartinUeding no, one can not just simply kill a thread. If your thread has called `new` and the impl happens to lock a mutex; all your threads will deadlock on their next call to new. – UKMonkey Mar 26 '18 at 15:19
  • Possible duplicate of [How do I terminate a thread in C++11?](https://stackoverflow.com/questions/12207684/how-do-i-terminate-a-thread-in-c11), however. – Arne Vogel Mar 26 '18 at 16:04
  • `One is that I can't forcibly terminate the std::future object` Huh?! `std::future* p = new std::future(); ... ; delete p;` – Severin Pappadeux Mar 26 '18 at 16:24
  • Possible duplicate of [How do I terminate a thread in C++11?](https://stackoverflow.com/questions/12207684/how-do-i-terminate-a-thread-in-c11) – Passer By Mar 26 '18 at 16:56
  • @SeverinPappadeux I guess, you have no idea what the question is about. – SergeyA Mar 26 '18 at 17:36
  • @SergeyA you guessed it wrong – Severin Pappadeux Mar 26 '18 at 17:54
  • 2
    @SeverinPappadeux in this case please kindly explain how deleting an allocated future object is going to terminate it's execution thread. Ideally with reference to the documentation and code to show this. – SergeyA Mar 26 '18 at 18:17

1 Answers1

2

You are out of luck, sorry.

First off, C++ doesn't even guarantee you there will be a thread for future execution. Although it would be extremely hard (probably impossible) to implement all std::async guarantees in a single thread, there is no direct prohibition of that, and also, there is certainly no guarantee that there will be a thread per async call. Because of that, there is no way to cancel the async execution.

Second, there is no such way even in the lowest level of thread implementation. While pthread_cancel exists, it won't protect you from infinite loops not visiting cancellation points, for example.

You can not arbitrarily kill a thread in Posix, and C++ thread model is based on it. A process really can't be a scheduler of it's own threads, and while sometimes it is a pain, it is what it is.

SergeyA
  • 61,605
  • 5
  • 78
  • 137