aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcoFalke <falke.marco@gmail.com>2019-02-04 14:26:02 -0500
committerMarcoFalke <falke.marco@gmail.com>2019-02-04 14:26:07 -0500
commit452acee4da206eb8792505914fd92245246b2290 (patch)
treeff6ee5e55cc96bd3f7b20a2669d547e4657920ca
parentbfbe42585e9b9a77623a95df54ec76adf91fccea (diff)
parent77777c5624e2f5416d85500e82b7c80e10ed01b6 (diff)
downloadbitcoin-452acee4da206eb8792505914fd92245246b2290.tar.xz
Merge #15266: memory: Construct globals on first use
77777c5624 log: Construct global logger on first use (MarcoFalke) Pull request description: The (de)initialization order is not well defined in C++, so generally it is not safe to use globals as the (de/con)structor of one global could use the (de/con)structor of another global before/after it has been (con/de)structed. Specifically this fixes: * `g_logger` might not be initialized on the first use, so do that. (Fixes #15111) Tree-SHA512: eb9c22f4baf31ebc5b0b9ee6a51d1354bae1f0df186cc0ce818b4483c7b5a7f90268d2b549ee96b4c57f8ef36ab239dc6497f74f3e2ef166038f7437c368297d
-rw-r--r--src/httpserver.cpp4
-rw-r--r--src/init.cpp28
-rw-r--r--src/interfaces/node.cpp2
-rw-r--r--src/logging.cpp8
-rw-r--r--src/logging.h8
-rw-r--r--src/rpc/misc.cpp12
6 files changed, 34 insertions, 28 deletions
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index ca60ea43a7..b9ca037c9d 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 019b2e469e..b3c99c4382 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 c574f960e6..a2b89c3f90 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 77dc2d0939..36cad6573a 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 0c8e7f5291..ac9d0dc0c7 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 <typename... Args>
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 9d17a2fc4e..8850cf066b 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.");
}