This is intentionally a near-duplicate of: boost cobalt+asio not throwing exceptions correctly?
The difference is that the other ticket uses boost cobalt (a library that sits on top of asio that adds a more "co-routiney" interface).
This ticket applies to only asio, without cobalt, and the code has been modified accordingly. You can use the same CMakeLists.txt as the cobalt ticket.
#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"); // Intentionally wrong; use www.google.com to make it work
// Print the resolved endpoints
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;
}
The solution to this ticket is I suspect the solution to both tickets.
Just to reiterate the problem: The code above works fine when passed a reasonable address (e.g., "www.google.com") but fails to throw an exception out of async_resolve() when passed an unreasonable address (e.g., "www.googleqqq.com").
What happens instead is that this prints out:
libc++abi: terminating due to uncaught exception of type boost::system::system_error: Host not found (authoritative) [asio.netdb:1]
and SIGABRT occurs (which probably means std::terminate was called). So none of the exception catching stuff in the code above was hit.
The answer is "it's a bug" (credit to @sehe for mentioning dynamic linking).
Relevant info: https://github.com/llvm/llvm-project/issues/92121
Solution (in CMakeLists.txt, assuming MacOS):
execute_process(
COMMAND brew --prefix llvm
OUTPUT_VARIABLE LLVM_PREFIX
OUTPUT_STRIP_TRAILING_WHITESPACE
)
target_link_libraries(${PROJECT_NAME}
PRIVATE
${LLVM_PREFIX}/lib/libunwind.dylib
)