std::future returned from std::async hangs while going out of scope

TheWaterProgrammer picture TheWaterProgrammer · Feb 16, 2017 · Viewed 7k times · Source

I am using a combination of std::async and std::future from C++ 11. I am using to enforce a time_out on a certain activity that I do in my code which might take time as I try connecting to server.

Following is how the code is:

#include <future>
#include <chrono>

std::size_t PotentiallyLongRunningActivity() {
    using namespace std::chrono_literals;
    std::this_thread::sleep_for(10000s);
    return 10;
}

bool DoActivity() {

  bool activity_done = false;
  auto my_future_result(std::async(std::launch::async, []() {
      return PotentiallyLongRunningActivity(); //returns size_t
  }));

  std::future_status my_future_status = my_future_result.wait_for(std::chrono::milliseconds(800));
  if (my_future_status == std::future_status::timeout) {
      activity_done = false;
  }
  else if (my_future_status == std::future_status::ready) {
      if (my_future_result.valid() && my_future_result.get() > 0) {
          activity_done = true;
      }
  }

  return activity_done;
  //my_future_result hangs while exiting this method !!!
}

int main(int argc, char *argv[])
{
    DoActivity();
    return 0;
}

Things work fine in most of the cases. The future times out & is reported ready in many cases. But, Strange behavior I am observing is that in some cases the UI hangs because my_future_result when going out of scope hangs. I confirmed this by repeating the call to my_future_result.get() which never returns if called just before exiting the method.

How can I get around this ? Is there some way I cancel or delete or terminate the std::future ?

Answer

Mikel F picture Mikel F · Feb 16, 2017

You are exiting your function before the std::async task has completed. Under certain circumstances, the destructor for a std::future will block until the task has completed.

http://en.cppreference.com/w/cpp/thread/future/wait_for

Here in the documentation for wait_for the example shows multiple calls to wait_for after timeouts, showing that the act of timing out does not cancel the std::async task.

There is no built-in support (that I could discover) that allows for threads to be killed externally. This makes sense as there isn't a way to properly clean up the state of system resources in use by the thread if it is terminated in this way.

Instead, it is better to place the timeout logic in the thread itself, so that it can terminate itself and clean up properly.