c++ - std::promise set_exception 两次导致段错误

标签 c++ c++14 c++17 std-future

假设我有一个调用不稳定的第三方服务的方法,所以我为这个调用添加了一个超时时间,比如 10 秒。这是我尝试过的:

int process()
{
    std::promise<int> promise;
    std::future<int> future = promise.get_future();

    std::thread([&]
    {
        try
        {
            int result = call_third_party_service();
            promise.set_value(result);
        }
        catch (std::exception&) //call_thrid_party_service can throw exceptions
        {
            promise.set_exception(std::current_exception());
        }
    }).detach();

    auto status = future.wait_for(std::chrono::seconds(10));
    if (status == std::future_status::timeout)
    {
        promise.set_exception(time_out_exception);
    }

    return future.get();
}

int main()
{
    try
    {
        int result = process();
    }
    catch(const std::exception& e)
    {
        //print
    }

    //blocks the thread to see what happens
    std::this_thread::sleep_for(std::chrono::minutes(1));        
    return 0;
}

call_third_party_service 没有响应时(假设它在 30 秒后抛出异常提示超时),status == std::future_status::timeout 在 10 秒后命中等待,然后 promise.set_exception 工作,一切看起来都很好。但是,当 call_third_party_service 抛出异常时,promise.set_exception 再次抛出,因此出现 Segmentation 错误。实现此模式的正确方法是什么?

最佳答案

根据Frax的建议,您应该将promise移到lambda中,并在future超时时直接抛出异常:

int process() {
  std::promise<int> promise;
  std::future<int> future = promise.get_future();

  // move ownership of the promise into thread
  std::thread([prom = std::move(promise)]() mutable {
    try {
      int result = call_third_party_service();
      prom.set_value(result);
    } catch (std::exception&)  // call_thrid_party_service can throw exceptions
    {
      prom.set_exception(std::current_exception());
    }
  }).detach();

  auto status = future.wait_for(std::chrono::seconds(10));
  if (status == std::future_status::timeout) {
    // This exception is not part of an asynchronous computation and 
    // should be thrown immediately
    throw time_out_exception("timed out");
  }

  return future.get();
}

int main() {
  try {
    int result = process();
  } catch (const std::exception& e) {
    // print
  }

  // blocks the thread to see what happens
  std::this_thread::sleep_for(std::chrono::minutes(1)); 
  return 0;
}

关于c++ - std::promise set_exception 两次导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55915552/

相关文章:

c++ - 如果我在与 char 比较之前没有明确地将 int 转换为 char,这有关系吗?

c++ - 为什么字符串的 move() 会更改内存中的基础数据位置?

c++ - 错误 :no override found for 'vtkPolyDataMapper'

c++ - 我们在 C++ 中使用 "inherit"构造函数吗? "inheriting"的确切定义是什么

c++ - 隐藏结构细节的迭代器适配器

linux - 在 Amazon Linux 上安装 g++ 5

c++ - 对 2 个 "linked"数组进行排序的更好方法?

c++ - 我可以使用reduce代替for循环吗?

c++ - 使用引用的 constexpr 静态成员作为模板参数

C++为什么读取二进制文件会跳到最后