diff --git a/src/httpserver.cpp b/src/httpserver.cpp index ca60ea43a..b9ca037c9 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -364,8 +364,8 @@ bool InitHTTPServer() // Update libevent's log handling. Returns false if our version of // libevent doesn't support debug logging, in which case we should // clear the BCLog::LIBEVENT flag. - if (!UpdateHTTPServerLogging(g_logger->WillLogCategory(BCLog::LIBEVENT))) { - g_logger->DisableCategory(BCLog::LIBEVENT); + if (!UpdateHTTPServerLogging(LogInstance().WillLogCategory(BCLog::LIBEVENT))) { + LogInstance().DisableCategory(BCLog::LIBEVENT); } #ifdef WIN32 diff --git a/src/init.cpp b/src/init.cpp index 019b2e469..b3c99c438 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -289,7 +289,7 @@ static void HandleSIGTERM(int) static void HandleSIGHUP(int) { - g_logger->m_reopen_file = true; + LogInstance().m_reopen_file = true; } #else static BOOL WINAPI consoleCtrlHandler(DWORD dwCtrlType) @@ -833,17 +833,17 @@ static std::string ResolveErrMsg(const char * const optname, const std::string& */ void InitLogging() { - g_logger->m_print_to_file = !gArgs.IsArgNegated("-debuglogfile"); - g_logger->m_file_path = AbsPathForConfigVal(gArgs.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE)); + LogInstance().m_print_to_file = !gArgs.IsArgNegated("-debuglogfile"); + LogInstance().m_file_path = AbsPathForConfigVal(gArgs.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE)); // Add newlines to the logfile to distinguish this execution from the last // one; called before console logging is set up, so this is only sent to // debug.log. LogPrintf("\n\n\n\n\n"); - g_logger->m_print_to_console = gArgs.GetBoolArg("-printtoconsole", !gArgs.GetBoolArg("-daemon", false)); - g_logger->m_log_timestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS); - g_logger->m_log_time_micros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS); + LogInstance().m_print_to_console = gArgs.GetBoolArg("-printtoconsole", !gArgs.GetBoolArg("-daemon", false)); + LogInstance().m_log_timestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS); + LogInstance().m_log_time_micros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS); fLogIPs = gArgs.GetBoolArg("-logips", DEFAULT_LOGIPS); @@ -981,7 +981,7 @@ bool AppInitParameterInteraction() if (std::none_of(categories.begin(), categories.end(), [](std::string cat){return cat == "0" || cat == "none";})) { for (const auto& cat : categories) { - if (!g_logger->EnableCategory(cat)) { + if (!LogInstance().EnableCategory(cat)) { InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debug", cat)); } } @@ -990,7 +990,7 @@ bool AppInitParameterInteraction() // Now remove the logging categories which were explicitly excluded for (const std::string& cat : gArgs.GetArgs("-debugexclude")) { - if (!g_logger->DisableCategory(cat)) { + if (!LogInstance().DisableCategory(cat)) { InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debugexclude", cat)); } } @@ -1197,19 +1197,19 @@ bool AppInitMain(InitInterfaces& interfaces) #ifndef WIN32 CreatePidFile(GetPidFile(), getpid()); #endif - if (g_logger->m_print_to_file) { - if (gArgs.GetBoolArg("-shrinkdebugfile", g_logger->DefaultShrinkDebugFile())) { + if (LogInstance().m_print_to_file) { + if (gArgs.GetBoolArg("-shrinkdebugfile", LogInstance().DefaultShrinkDebugFile())) { // Do this first since it both loads a bunch of debug.log into memory, // and because this needs to happen before any other debug.log printing - g_logger->ShrinkDebugFile(); + LogInstance().ShrinkDebugFile(); } - if (!g_logger->OpenDebugLog()) { + if (!LogInstance().OpenDebugLog()) { return InitError(strprintf("Could not open debug log file %s", - g_logger->m_file_path.string())); + LogInstance().m_file_path.string())); } } - if (!g_logger->m_log_timestamps) + if (!LogInstance().m_log_timestamps) LogPrintf("Startup time: %s\n", FormatISO8601DateTime(GetTime())); LogPrintf("Default data directory %s\n", GetDefaultDataDir().string()); LogPrintf("Using data directory %s\n", GetDataDir().string()); diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp index c574f960e..a2b89c3f9 100644 --- a/src/interfaces/node.cpp +++ b/src/interfaces/node.cpp @@ -67,7 +67,7 @@ public: void initLogging() override { InitLogging(); } void initParameterInteraction() override { InitParameterInteraction(); } std::string getWarnings(const std::string& type) override { return GetWarnings(type); } - uint32_t getLogCategories() override { return g_logger->GetCategoryMask(); } + uint32_t getLogCategories() override { return LogInstance().GetCategoryMask(); } bool baseInitialize() override { return AppInitBasicSetup() && AppInitParameterInteraction() && AppInitSanityChecks() && diff --git a/src/logging.cpp b/src/logging.cpp index 77dc2d093..36cad6573 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -8,6 +8,8 @@ const char * const DEFAULT_DEBUGLOGFILE = "debug.log"; +BCLog::Logger& LogInstance() +{ /** * NOTE: the logger instances is leaked on exit. This is ugly, but will be * cleaned up by the OS/libc. Defining a logger as a global object doesn't work @@ -17,11 +19,15 @@ const char * const DEFAULT_DEBUGLOGFILE = "debug.log"; * access the logger. When the shutdown sequence is fully audited and tested, * explicit destruction of these objects can be implemented by changing this * from a raw pointer to a std::unique_ptr. + * Since the destructor is never called, the logger and all its members must + * have a trivial destructor. * * This method of initialization was originally introduced in * ee3374234c60aba2cc4c5cd5cac1c0aefc2d817c. */ -BCLog::Logger* const g_logger = new BCLog::Logger(); + static BCLog::Logger* g_logger{new BCLog::Logger()}; + return *g_logger; +} bool fLogIPs = DEFAULT_LOGIPS; diff --git a/src/logging.h b/src/logging.h index 0c8e7f529..ac9d0dc0c 100644 --- a/src/logging.h +++ b/src/logging.h @@ -108,12 +108,12 @@ namespace BCLog { } // namespace BCLog -extern BCLog::Logger* const g_logger; +BCLog::Logger& LogInstance(); /** Return true if log accepts specified category */ static inline bool LogAcceptCategory(BCLog::LogFlags category) { - return g_logger->WillLogCategory(category); + return LogInstance().WillLogCategory(category); } /** Returns a string with the log categories. */ @@ -132,7 +132,7 @@ bool GetLogCategory(BCLog::LogFlags& flag, const std::string& str); template static inline void LogPrintf(const char* fmt, const Args&... args) { - if (g_logger->Enabled()) { + if (LogInstance().Enabled()) { std::string log_msg; try { log_msg = tfm::format(fmt, args...); @@ -140,7 +140,7 @@ static inline void LogPrintf(const char* fmt, const Args&... args) /* Original format string will have newline so don't add one here */ log_msg = "Error \"" + std::string(fmterr.what()) + "\" while formatting log message: " + fmt; } - g_logger->LogPrintStr(log_msg); + LogInstance().LogPrintStr(log_msg); } } diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 9d17a2fc4..8850cf066 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -366,9 +366,9 @@ static void EnableOrDisableLogCategories(UniValue cats, bool enable) { bool success; if (enable) { - success = g_logger->EnableCategory(cat); + success = LogInstance().EnableCategory(cat); } else { - success = g_logger->DisableCategory(cat); + success = LogInstance().DisableCategory(cat); } if (!success) { @@ -415,14 +415,14 @@ UniValue logging(const JSONRPCRequest& request) }.ToString()); } - uint32_t original_log_categories = g_logger->GetCategoryMask(); + uint32_t original_log_categories = LogInstance().GetCategoryMask(); if (request.params[0].isArray()) { EnableOrDisableLogCategories(request.params[0], true); } if (request.params[1].isArray()) { EnableOrDisableLogCategories(request.params[1], false); } - uint32_t updated_log_categories = g_logger->GetCategoryMask(); + uint32_t updated_log_categories = LogInstance().GetCategoryMask(); uint32_t changed_log_categories = original_log_categories ^ updated_log_categories; // Update libevent logging if BCLog::LIBEVENT has changed. @@ -431,8 +431,8 @@ UniValue logging(const JSONRPCRequest& request) // Throw an error if the user has explicitly asked to change only the libevent // flag and it failed. if (changed_log_categories & BCLog::LIBEVENT) { - if (!UpdateHTTPServerLogging(g_logger->WillLogCategory(BCLog::LIBEVENT))) { - g_logger->DisableCategory(BCLog::LIBEVENT); + if (!UpdateHTTPServerLogging(LogInstance().WillLogCategory(BCLog::LIBEVENT))) { + LogInstance().DisableCategory(BCLog::LIBEVENT); if (changed_log_categories == BCLog::LIBEVENT) { throw JSONRPCError(RPC_INVALID_PARAMETER, "libevent logging cannot be updated when using libevent before v2.1.1."); }