diff --git a/yt/yt/core/logging/log_manager.cpp b/yt/yt/core/logging/log_manager.cpp index 5209a253..8d7baba7 100644 --- a/yt/yt/core/logging/log_manager.cpp +++ b/yt/yt/core/logging/log_manager.cpp @@ -348,26 +348,52 @@ class TLogManager::TImpl RegisterWriterFactory(TString(TStderrLogWriterConfig::WriterType), GetStderrLogWriterFactory()); } + bool IsInitialized() const + { + return InitializationFinished_.Test(); + } + void Initialize() { - std::call_once(Initialized_, [&] { - // NB: Cannot place this logic inside ctor since it may boot up Compression threads unexpected - // and these will try to access TLogManager instance causing a deadlock. - try { - if (auto config = TLogManagerConfig::TryCreateFromEnv()) { - DoUpdateConfig(config, /*fromEnv*/ true); - } - } catch (const std::exception& ex) { - fprintf(stderr, "Error configuring logging from environment variables\n%s\n", - ex.what()); + [[likely]] if (InitializationFinished_.Test()) { + // Don't bother doing syscalls on a hot path. + return; + } + + // Sync is done via event so there is no need for stronger memory orders. + // Case of recursive call is alright, because there sync is done via sequenced-before ordering. + [[likely]] if (InitializationStarted_.exchange(true, std::memory_order::relaxed)) { + NThreading::TThreadId initializerThreadId = NThreading::InvalidThreadId; + while (initializerThreadId == NThreading::InvalidThreadId) { + initializerThreadId = InitializerThreadId_.load(std::memory_order::relaxed); + } + if (GetCurrentThreadId() == initializerThreadId) { + // Recursive call -- bail out. + return; } + // Another thread -- now wait for real. + InitializationFinished_.Wait(); + return; + } + InitializerThreadId_.store(GetCurrentThreadId(), std::memory_order::relaxed); - if (!IsConfiguredFromEnv()) { - DoUpdateConfig(TLogManagerConfig::CreateDefault(), /*fromEnv*/ false); + // NB: Cannot place this logic inside ctor since it may boot up Compression threads unexpected + // and these will try to access TLogManager instance causing a deadlock. + try { + if (auto config = TLogManagerConfig::TryCreateFromEnv()) { + DoUpdateConfig(config, /*fromEnv*/ true); } + } catch (const std::exception& ex) { + fprintf(stderr, "Error configuring logging from environment variables\n%s\n", + ex.what()); + } - SystemCategory_ = GetCategory(SystemLoggingCategoryName); - }); + if (!IsConfiguredFromEnv()) { + DoUpdateConfig(TLogManagerConfig::CreateDefault(), /*fromEnv*/ false); + } + + SystemCategory_ = GetCategory(SystemLoggingCategoryName); + InitializationFinished_.NotifyAll(); } void Configure(INodePtr node) @@ -1347,7 +1373,10 @@ class TLogManager::TImpl std::atomic HighBacklogWatermark_ = Max(); std::atomic LowBacklogWatermark_ = Max(); - std::once_flag Initialized_; + std::atomic InitializationStarted_ = false; + std::atomic InitializerThreadId_ = NThreading::InvalidThreadId; + NThreading::TEvent InitializationFinished_; + std::once_flag Started_; std::atomic Suspended_ = false; std::atomic ScheduledOutOfBand_ = false; @@ -1431,105 +1460,155 @@ TLogManager::~TLogManager() = default; TLogManager* TLogManager::Get() { auto* logManager = LeakySingleton(); - logManager->Initialize(); + logManager->Impl_->Initialize(); return logManager; } void TLogManager::Configure(TLogManagerConfigPtr config, bool sync) { + [[unlikely]] if (!Impl_->IsInitialized()) { + return; + } Impl_->Configure(std::move(config), /*fromEnv*/ false, sync); } void TLogManager::ConfigureFromEnv() { + [[unlikely]] if (!Impl_->IsInitialized()) { + return; + } Impl_->ConfigureFromEnv(); } bool TLogManager::IsConfiguredFromEnv() { + [[unlikely]] if (!Impl_->IsInitialized()) { + return false; + } return Impl_->IsConfiguredFromEnv(); } void TLogManager::Shutdown() { + [[unlikely]] if (!Impl_->IsInitialized()) { + return; + } Impl_->Shutdown(); } int TLogManager::GetVersion() const { + [[unlikely]] if (!Impl_->IsInitialized()) { + return 0; + } return Impl_->GetVersion(); } bool TLogManager::GetAbortOnAlert() const { + [[unlikely]] if (!Impl_->IsInitialized()) { + return false; + } return Impl_->GetAbortOnAlert(); } const TLoggingCategory* TLogManager::GetCategory(TStringBuf categoryName) { + [[unlikely]] if (!Impl_->IsInitialized()) { + return nullptr; + } return Impl_->GetCategory(categoryName); } void TLogManager::UpdateCategory(TLoggingCategory* category) { + [[unlikely]] if (!Impl_->IsInitialized()) { + return; + } Impl_->UpdateCategory(category); } void TLogManager::UpdateAnchor(TLoggingAnchor* anchor) { + [[unlikely]] if (!Impl_->IsInitialized()) { + return; + } Impl_->UpdateAnchor(anchor); } void TLogManager::RegisterStaticAnchor(TLoggingAnchor* anchor, ::TSourceLocation sourceLocation, TStringBuf anchorMessage) { + [[unlikely]] if (!Impl_->IsInitialized()) { + return; + } Impl_->RegisterStaticAnchor(anchor, sourceLocation, anchorMessage); } TLoggingAnchor* TLogManager::RegisterDynamicAnchor(TString anchorMessage) { + [[unlikely]] if (!Impl_->IsInitialized()) { + return nullptr; + } return Impl_->RegisterDynamicAnchor(std::move(anchorMessage)); } void TLogManager::RegisterWriterFactory(const TString& typeName, const ILogWriterFactoryPtr& factory) { + [[unlikely]] if (!Impl_->IsInitialized()) { + return; + } Impl_->RegisterWriterFactory(typeName, factory); } void TLogManager::UnregisterWriterFactory(const TString& typeName) { + [[unlikely]] if (!Impl_->IsInitialized()) { + return; + } Impl_->UnregisterWriterFactory(typeName); } void TLogManager::Enqueue(TLogEvent&& event) { + [[unlikely]] if (!Impl_->IsInitialized()) { + Cerr << NYT::Format("Trying to log event during logger initialization -- skipping") << Endl; + return; + } Impl_->Enqueue(std::move(event)); } void TLogManager::Reopen() { + [[unlikely]] if (!Impl_->IsInitialized()) { + return; + } Impl_->Reopen(); } void TLogManager::EnableReopenOnSighup() { + [[unlikely]] if (!Impl_->IsInitialized()) { + return; + } Impl_->EnableReopenOnSighup(); } void TLogManager::SuppressRequest(TRequestId requestId) { + [[unlikely]] if (!Impl_->IsInitialized()) { + return; + } Impl_->SuppressRequest(requestId); } void TLogManager::Synchronize(TInstant deadline) { + [[unlikely]] if (!Impl_->IsInitialized()) { + return; + } Impl_->Synchronize(deadline); } -void TLogManager::Initialize() -{ - Impl_->Initialize(); -} - //////////////////////////////////////////////////////////////////////////////// TFiberMinLogLevelGuard::TFiberMinLogLevelGuard(ELogLevel minLogLevel) diff --git a/yt/yt/core/logging/log_manager.h b/yt/yt/core/logging/log_manager.h index 08598d30..e4309e32 100644 --- a/yt/yt/core/logging/log_manager.h +++ b/yt/yt/core/logging/log_manager.h @@ -70,8 +70,6 @@ class TLogManager DECLARE_LEAKY_SINGLETON_FRIEND() - void Initialize(); - class TImpl; const TIntrusivePtr Impl_; };