You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Boost Asio(含协程)async_resolve异常未正确抛出问题

Boost Asio协程中async_resolve异常未被正确捕获的问题

问题描述

以下纯Boost Asio协程代码,解析合法地址(如www.google.com)时运行正常,但传入无效地址(如www.googleqqq.com)时,async_resolve未触发代码中的异常捕获逻辑,直接触发SIGABRT,输出如下错误信息:

libc++abi: terminating due to uncaught exception of type boost::system::system_error: Host not found (authoritative) [asio.netdb:1]

代码中的所有try/catch块均未捕获到该异常,最终程序因std::terminate调用而终止。

复现代码

#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>

#include <iostream>
#include <string>
#include <vector>

namespace net = boost::asio;
using executor_type =  net::any_io_executor;

net::awaitable<std::vector<net::ip::tcp::endpoint>> resolve(
    executor_type executor,
    std::string const& hostname,
    std::string const& service
)
{
    auto endpoints = std::vector<net::ip::tcp::endpoint>{};
    auto resolver = net::ip::tcp::resolver{executor};
    try
    {
        auto results = co_await resolver.async_resolve(hostname, service, net::use_awaitable);

        for (const auto& result : results)
            endpoints.push_back(result.endpoint());

        co_return endpoints;
    }
    catch (...)
    {
        std::cerr << "Resolve exception\n";
        throw;
    }
}

net::awaitable<void> main2()
{
    auto executor = co_await net::this_coro::executor;

    auto endpoints = co_await resolve(executor, "www.googleqqq.com", "https"); // 故意使用无效地址,替换为www.google.com可正常运行

    // 打印解析后的端点
    for (const auto& endpoint : endpoints)
        std::cerr << endpoint << std::endl;

    co_return;
}

int main()
{
    try
    {
        net::io_context ctx;
        net::co_spawn(
            ctx,
            main2(),
            [&](std::exception_ptr eptr)
            {
                try
                {
                    if (eptr)
                        std::rethrow_exception(eptr);
                }
                catch (const std::exception& e)
                {
                    std::cerr << "Exception: " << e.what() << std::endl;
                }
            });
        ctx.run();
    }
    catch (...)
    {
        std::cerr << "Uncaught exception\n";
    }
    return 0;
}

解决方案

方案1:扩展异常捕获范围

问题核心是完成处理函数仅捕获std::exception类型异常,若存在非标准异常类型则会漏捕。修改co_spawn的完成处理函数,添加全量异常捕获:

[&](std::exception_ptr eptr)
{
    try
    {
        if (eptr)
            std::rethrow_exception(eptr);
    }
    catch (const std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << std::endl;
    }
    catch (...)
    {
        std::cerr << "捕获到未知类型异常" << std::endl;
    }
}

方案2:手动处理错误码

避免依赖协程自动抛出异常,改用redirect_error将错误码显式传递,手动判断并抛出异常:

net::awaitable<std::vector<net::ip::tcp::endpoint>> resolve(
    executor_type executor,
    std::string const& hostname,
    std::string const& service
)
{
    auto endpoints = std::vector<net::ip::tcp::endpoint>{};
    auto resolver = net::ip::tcp::resolver{executor};
    boost::system::error_code ec;
    auto results = co_await resolver.async_resolve(hostname, service, net::redirect_error(net::use_awaitable, ec));
    
    if (ec) {
        std::cerr << "Resolve error: " << ec.message() << "\n";
        throw boost::system::system_error(ec);
    }

    for (const auto& result : results)
        endpoints.push_back(result.endpoint());

    co_return endpoints;
}

额外注意

旧版本Boost Asio的协程模块存在异常传递bug,建议使用Boost 1.78及以上版本。

内容的提问来源于stack exchange,提问作者user5406764

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 18:15:58