diff --git a/source/common/network/dns_impl.cc b/source/common/network/dns_impl.cc index bb317ae397f03..5153c35ffcabb 100644 --- a/source/common/network/dns_impl.cc +++ b/source/common/network/dns_impl.cc @@ -120,8 +120,18 @@ void DnsResolverImpl::PendingResolution::onAresHostCallback(int status, int time if (completed_) { if (!cancelled_) { - dispatcher_.post( - [callback = callback_, al = std::move(address_list)] { callback(std::move(al)); }); + try { + callback_(std::move(address_list)); + } catch (const EnvoyException& e) { + ENVOY_LOG(critical, "EnvoyException in c-ares callback"); + dispatcher_.post([e] { throw e; }); + } catch (const std::exception& e) { + ENVOY_LOG(critical, "std::exception in c-ares callback"); + dispatcher_.post([s = std::string(e.what())] { throw EnvoyException(s); }); + } catch (...) { + ENVOY_LOG(critical, "Unknown exception in c-ares callback"); + dispatcher_.post([] { throw EnvoyException("unknown"); }); + } } if (owned_) { delete this; diff --git a/source/common/network/dns_impl.h b/source/common/network/dns_impl.h index 2f79190e8e18b..1dad26e11a017 100644 --- a/source/common/network/dns_impl.h +++ b/source/common/network/dns_impl.h @@ -64,7 +64,7 @@ class DnsResolverImpl : public DnsResolver, protected Logger::Loggable&& results) -> void { address_list = results; })); - dispatcher_.run(Event::Dispatcher::RunType::NonBlock); EXPECT_TRUE(hasAddress(address_list, "127.0.0.1")); EXPECT_FALSE(hasAddress(address_list, "::1")); } @@ -507,7 +506,6 @@ TEST_P(DnsImplTest, LocalLookup) { address_list = results; })) << error_msg; - dispatcher_.run(Event::Dispatcher::RunType::NonBlock); EXPECT_TRUE(hasAddress(address_list, "::1")) << error_msg; EXPECT_FALSE(hasAddress(address_list, "127.0.0.1")); @@ -517,7 +515,6 @@ TEST_P(DnsImplTest, LocalLookup) { address_list = results; })) << error_msg; - dispatcher_.run(Event::Dispatcher::RunType::NonBlock); EXPECT_FALSE(hasAddress(address_list, "127.0.0.1")); EXPECT_TRUE(hasAddress(address_list, "::1")) << error_msg; } @@ -557,6 +554,29 @@ TEST_P(DnsImplTest, DnsIpAddressVersionV6) { EXPECT_TRUE(hasAddress(address_list, "1::2")); } +// Validate exception behavior during c-ares callbacks. +TEST_P(DnsImplTest, CallbackException) { + // Force immediate resolution, which will trigger a c-ares exception unsafe + // state providing regression coverage for #4307. + EXPECT_EQ(nullptr, resolver_->resolve( + "1.2.3.4", DnsLookupFamily::V4Only, + [&](const std::list && + /*results*/) -> void { throw EnvoyException("Envoy exception"); })); + EXPECT_THROW_WITH_MESSAGE(dispatcher_.run(Event::Dispatcher::RunType::Block), EnvoyException, + "Envoy exception"); + EXPECT_EQ(nullptr, resolver_->resolve( + "1.2.3.4", DnsLookupFamily::V4Only, + [&](const std::list && + /*results*/) -> void { throw std::runtime_error("runtime error"); })); + EXPECT_THROW_WITH_MESSAGE(dispatcher_.run(Event::Dispatcher::RunType::Block), EnvoyException, + "runtime error"); + EXPECT_EQ(nullptr, resolver_->resolve("1.2.3.4", DnsLookupFamily::V4Only, + [&](const std::list && + /*results*/) -> void { throw std::string(); })); + EXPECT_THROW_WITH_MESSAGE(dispatcher_.run(Event::Dispatcher::RunType::Block), EnvoyException, + "unknown"); +} + TEST_P(DnsImplTest, DnsIpAddressVersion) { std::list address_list; server_->addHosts("some.good.domain", {"1.2.3.4"}, A);