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
相关产品推荐
相关产品推荐

