微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

boost::asio::co_spawn 不会传播异常

如何解决boost::asio::co_spawn 不会传播异常

我正在涉足关于 boost::asio 的协程,但我对异常处理感到困惑。根据文档的 examples in 判断,似乎任何“失败”error_code 都变成了异常 - 所以我希望抛出的任何异常都会也会传播回 co_spawn 调用。但事实并非如此:

#define BOOST_ASIO_HAS_CO_AWAIT
#define BOOST_ASIO_HAS_STD_COROUTINE

#include <iostream>

#include <boost/asio/awaitable.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/executor_work_guard.hpp>

namespace this_coro = boost::asio::this_coro;

boost::asio::awaitable<void> async_op()
{
    std::cout << "About to throw" << std::endl;
    throw std::runtime_error{"Bang!"};
}

int main()
{
    auto ctx = boost::asio::io_context{};
    auto guard = boost::asio::make_work_guard(ctx.get_executor());

    boost::asio::co_spawn(ctx,async_op,boost::asio::detached);

    ctx.run();
}

如果这是在调试器中运行,您可以看到抛出的异常,但它似乎只是挂起。暂停调试器表明 ctx.run() 正在等待新工作(由于 executor_work_guard)。所以看起来 boost::asio 里面的东西已经地吞下了这个异常。

作为实验,我将异步操作切换为使用 boost::asio 库调用

boost::asio::awaitable<void> async_op()
{
    auto executor = co_await this_coro::executor;
    auto socket = boost::asio::ip::tcp::socket{executor};

    std::cout << "Starting resolve" << std::endl;
    auto resolver = boost::asio::ip::tcp::resolver{executor};
    const auto endpoints = co_await resolver.async_resolve("localhost","4444",boost::asio::use_awaitable);



    std::cout << "Starting connect (num endpoints: " << endpoints.size() << ")" << std::endl;
    co_await boost::asio::async_connect(socket,endpoints,boost::asio::use_awaitable);
    std::cout << "Exited" << std::endl;
}

我没有在端口 4444 上运行的服务器,所以这应该会立即失败 - 并且它会以静方式运行。暂停调试器表明它卡在 epoll 等待某事(我在 Linux 上)。

async_connect CompletionToken 交换为 boost::asio::redirect_error 表明操作失败:

co_await boost::asio::async_connect(socket,boost::asio::redirect_error(boost::asio::use_awaitable,ec));
std::cout << "Exited: " << ec.message() << std::endl;

产量:

Starting resolve
Starting connect (num endpoints: 1)
Exited: Connection refused

那么我如何传播异常,并从 error_code 中创建它们,而不是 boost::asio 中的协程?

解决方法

boost::asio::co_spawn 创建一个 separate thread。这意味着不会传播异常。您可以在此处阅读更多相关信息:

但是 co_spawn 支持带有签名 void(std::exception_ptr,R) 的完成处理程序。在您的示例中,您使用了 boost::asio::detached,这意味着忽略完成结果。简单地传播它write a custom handler

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?