diff --git a/source/exe/process_wide.cc b/source/exe/process_wide.cc index 327a4c38eebd9..df421084a21b1 100644 --- a/source/exe/process_wide.cc +++ b/source/exe/process_wide.cc @@ -9,16 +9,27 @@ namespace Envoy { namespace { + +struct InitData { + uint32_t count_ ABSL_GUARDED_BY(mutex_){}; + absl::Mutex mutex_; +}; + // Static variable to count initialization pairs. For tests like // main_common_test, we need to count to avoid double initialization or // shutdown. -std::atomic& processWideInitialized() { - MUTABLE_CONSTRUCT_ON_FIRST_USE(std::atomic); -}; +InitData& processWideInitData() { MUTABLE_CONSTRUCT_ON_FIRST_USE(InitData); }; } // namespace ProcessWide::ProcessWide() { - if (processWideInitialized()++ == 0) { + // Note that the following lock has the dual use of making sure that initialization is complete + // before a second caller can enter and leave this function. + auto& init_data = processWideInitData(); + absl::MutexLock lock(&init_data.mutex_); + + 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(); @@ -42,10 +53,11 @@ ProcessWide::ProcessWide() { } ProcessWide::~ProcessWide() { - auto& process_wide_initialized = processWideInitialized(); - ASSERT(process_wide_initialized > 0); - if (--process_wide_initialized == 0) { - process_wide_initialized = false; + auto& init_data = processWideInitData(); + absl::MutexLock lock(&init_data.mutex_); + + ASSERT(init_data.count_ > 0); + if (--init_data.count_ == 0) { ares_library_cleanup(); } }