diff --git a/envoy/network/dns_resolver.h b/envoy/network/dns_resolver.h index 2a326f152fe83..3562f8756e94f 100644 --- a/envoy/network/dns_resolver.h +++ b/envoy/network/dns_resolver.h @@ -15,7 +15,7 @@ constexpr absl::string_view DnsResolverCategory = "envoy.network.dns_resolver"; class DnsResolverFactory : public Config::TypedFactory { public: - /* + /** * @returns a DnsResolver object. * @param dispatcher: the local dispatcher thread * @param api: API interface to interact with system resources @@ -26,6 +26,33 @@ class DnsResolverFactory : public Config::TypedFactory { const envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config) const PURE; std::string category() const override { return std::string(DnsResolverCategory); } + + /** + * Initialize the related data for this type of DNS resolver. + * For some DNS resolvers, like c-ares, there are some specific data structure + * needs to be initialized before using it to resolve target. + */ + virtual void initialize() {} + + /** + * Cleanup the related data for this type of DNS resolver. + * For some DNS resolvers, like c-ares, there are some specific data structure + * needs to be cleaned up before terminates Envoy. + */ + virtual void terminate() {} + + /** + * Create the DNS resolver factory based on the typed config and initialize it. + * @returns the DNS Resolver factory. + * @param typed_dns_resolver_config: the typed DNS resolver config + */ + static Network::DnsResolverFactory& + createFactory(const envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config); + + /** + * Call the terminate method on all the registered DNS resolver factories. + */ + static void terminateFactories(); }; } // namespace Network diff --git a/source/common/network/dns_resolver/dns_factory_util.cc b/source/common/network/dns_resolver/dns_factory_util.cc index d8d1712cab956..d06f1186fb561 100644 --- a/source/common/network/dns_resolver/dns_factory_util.cc +++ b/source/common/network/dns_resolver/dns_factory_util.cc @@ -79,8 +79,7 @@ void handleLegacyDnsResolverData( Network::DnsResolverFactory& createDnsResolverFactoryFromTypedConfig( const envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config) { ENVOY_LOG_MISC(debug, "create DNS resolver type: {}", typed_dns_resolver_config.name()); - return Config::Utility::getAndCheckFactory( - typed_dns_resolver_config); + return DnsResolverFactory::createFactory(typed_dns_resolver_config); } // Create the default DNS resolver factory. apple for MacOS or c-ares for all others. @@ -92,5 +91,19 @@ Network::DnsResolverFactory& createDefaultDnsResolverFactory( return createDnsResolverFactoryFromTypedConfig(typed_dns_resolver_config); } +Network::DnsResolverFactory& DnsResolverFactory::createFactory( + const envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config) { + auto& factory = + Config::Utility::getAndCheckFactory(typed_dns_resolver_config); + factory.initialize(); + return factory; +} + +void DnsResolverFactory::terminateFactories() { + auto& factories = Registry::FactoryRegistry::factories(); + std::for_each(factories.begin(), factories.end(), + [](auto& factory_it) { factory_it.second->terminate(); }); +} + } // namespace Network } // namespace Envoy diff --git a/source/exe/BUILD b/source/exe/BUILD index 994bc24231636..cc0796ed99007 100644 --- a/source/exe/BUILD +++ b/source/exe/BUILD @@ -141,11 +141,11 @@ envoy_cc_library( name = "process_wide_lib", srcs = ["process_wide.cc"], hdrs = ["process_wide.h"], - external_deps = ["ares"], deps = [ "//source/common/common:assert_lib", "//source/common/event:libevent_lib", "//source/common/http/http2:nghttp2_lib", + "//source/common/network/dns_resolver:dns_factory_util_lib", "//source/server:proto_descriptors_lib", ], ) diff --git a/source/exe/process_wide.cc b/source/exe/process_wide.cc index df421084a21b1..9e93e9c48f4b4 100644 --- a/source/exe/process_wide.cc +++ b/source/exe/process_wide.cc @@ -1,12 +1,12 @@ #include "source/exe/process_wide.h" +#include "envoy/network/dns_resolver.h" + #include "source/common/common/assert.h" #include "source/common/event/libevent.h" #include "source/common/http/http2/nghttp2.h" #include "source/server/proto_descriptors.h" -#include "ares.h" - namespace Envoy { namespace { @@ -30,7 +30,6 @@ ProcessWide::ProcessWide() { if (init_data.count_++ == 0) { // TODO(mattklein123): Audit the following as not all of these have to be re-initialized in the // edge case where something does init/destroy/init/destroy. - ares_library_init(ARES_LIB_INIT_ALL); Event::Libevent::Global::initialize(); Envoy::Server::validateProtoDescriptors(); Http::Http2::initializeNghttp2Logging(); @@ -58,7 +57,7 @@ ProcessWide::~ProcessWide() { ASSERT(init_data.count_ > 0); if (--init_data.count_ == 0) { - ares_library_cleanup(); + Network::DnsResolverFactory::terminateFactories(); } } diff --git a/source/extensions/network/dns_resolver/cares/dns_impl.cc b/source/extensions/network/dns_resolver/cares/dns_impl.cc index 35c147083be25..6d14b89fbe48d 100644 --- a/source/extensions/network/dns_resolver/cares/dns_impl.cc +++ b/source/extensions/network/dns_resolver/cares/dns_impl.cc @@ -493,7 +493,8 @@ DnsResolverImpl::AddrInfoPendingResolution::availableInterfaces() { } // c-ares DNS resolver factory -class CaresDnsResolverFactory : public DnsResolverFactory { +class CaresDnsResolverFactory : public DnsResolverFactory, + public Logger::Loggable { public: std::string name() const override { return std::string(CaresDnsResolver); } @@ -521,6 +522,29 @@ class CaresDnsResolverFactory : public DnsResolverFactory { } return std::make_shared(cares, dispatcher, resolvers); } + + void initialize() override { + // Initialize c-ares library in case first time. + absl::MutexLock lock(&mutex_); + if (!ares_library_initialized_) { + ares_library_initialized_ = true; + ENVOY_LOG(info, "c-ares library initialized."); + ares_library_init(ARES_LIB_INIT_ALL); + } + } + void terminate() override { + // Cleanup c-ares library if initialized. + absl::MutexLock lock(&mutex_); + if (ares_library_initialized_) { + ares_library_initialized_ = false; + ENVOY_LOG(info, "c-ares library cleaned up."); + ares_library_cleanup(); + } + } + +private: + bool ares_library_initialized_ ABSL_GUARDED_BY(mutex_){false}; + absl::Mutex mutex_; }; // Register the CaresDnsResolverFactory