Skip to content

Commit aa4d269

Browse files
committed
kernel: Drop global Logger instance
Change LogInstance() function to no longer allocate (and leak) a BCLog::Logger instance. Instead allow kernel applications to initialize their own logging instances that can be returned by LogInstance(). The LogInstance() function is not actually used for the majority of logging in kernel code. Most kernel log output goes directly to BCLog::Logger instances specified when kernel objects like ChainstateManager and CTxMemPool are constructed, which allows applications to create multiple Logger instances and control which log output is sent to them. The only kernel code that does rely on LogInstance() is certain low level code in the util library, like the RNG seeder, that is not passed a specific instance and needs to rely on the global LogInstance() function. Other code outside the kernel library uses LogInstance() heavily, and may continue to do so. bitcoind and test code now just create a log instance before the first LogInstance() call, which it returns, so all behavior is the same as before.
1 parent 3f69a25 commit aa4d269

23 files changed

+88
-51
lines changed

src/bench/bench_bitcoin.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <bench/bench.h>
66
#include <common/args.h>
77
#include <crypto/sha256.h>
8+
#include <logging.h>
89
#include <tinyformat.h>
910
#include <util/fs.h>
1011
#include <util/string.h>
@@ -62,6 +63,7 @@ static std::vector<std::string> parseTestSetupArgs(const ArgsManager& argsman)
6263

6364
int main(int argc, char** argv)
6465
{
66+
BCLog::Logger logger;
6567
ArgsManager argsman;
6668
SetupBenchArgs(argsman);
6769
SHA256AutoDetect();

src/bitcoin-cli.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <common/system.h>
1212
#include <compat/compat.h>
1313
#include <compat/stdin.h>
14+
#include <logging.h>
1415
#include <policy/feerate.h>
1516
#include <rpc/client.h>
1617
#include <rpc/mining.h>
@@ -1329,6 +1330,7 @@ static int CommandLineRPC(int argc, char *argv[])
13291330

13301331
MAIN_FUNCTION
13311332
{
1333+
BCLog::Logger logger;
13321334
SetupEnvironment();
13331335
if (!SetupNetworking()) {
13341336
tfm::format(std::cerr, "Error: Initializing networking failed\n");

src/bitcoin-tx.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <consensus/consensus.h>
1515
#include <core_io.h>
1616
#include <key_io.h>
17+
#include <logging.h>
1718
#include <policy/policy.h>
1819
#include <primitives/transaction.h>
1920
#include <script/script.h>
@@ -857,6 +858,7 @@ static int CommandLineRawTx(int argc, char* argv[])
857858

858859
MAIN_FUNCTION
859860
{
861+
BCLog::Logger logger;
860862
SetupEnvironment();
861863

862864
try {

src/bitcoin-util.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <common/system.h>
1414
#include <compat/compat.h>
1515
#include <core_io.h>
16+
#include <logging.h>
1617
#include <streams.h>
1718
#include <util/exception.h>
1819
#include <util/strencodings.h>
@@ -152,6 +153,7 @@ static int Grind(const std::vector<std::string>& args, std::string& strPrint)
152153
MAIN_FUNCTION
153154
{
154155
ArgsManager& args = gArgs;
156+
BCLog::Logger logger;
155157
SetupEnvironment();
156158

157159
try {

src/bitcoin-wallet.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ MAIN_FUNCTION
9595
{
9696
ArgsManager& args = gArgs;
9797

98+
BCLog::Logger logger;
99+
98100
int exit_status;
99101
std::unique_ptr<interfaces::Init> init = interfaces::MakeWalletInit(argc, argv, exit_status);
100102
if (!init) {

src/bitcoind.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <init.h>
1515
#include <interfaces/chain.h>
1616
#include <interfaces/init.h>
17+
#include <logging.h>
1718
#include <kernel/context.h>
1819
#include <node/context.h>
1920
#include <node/interface_ui.h>
@@ -259,6 +260,9 @@ static bool AppInit(NodeContext& node)
259260

260261
MAIN_FUNCTION
261262
{
263+
// Intentionally leaked! See BCLog::g_logger description for rationale.
264+
new BCLog::Logger;
265+
262266
NodeContext node;
263267
int exit_status;
264268
std::unique_ptr<interfaces::Init> init = interfaces::MakeNodeInit(node, argc, argv, exit_status);

src/kernel/bitcoinkernel.cpp

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,16 @@ using util::ImmediateTaskRunner;
5757
// library aren't required to export this symbol
5858
extern const TranslateFn G_TRANSLATION_FUN{nullptr};
5959

60-
static const kernel::Context btck_context_static{};
61-
6260
namespace {
6361

62+
// Log instance for kernel applications that don't create any logging
63+
// connections and don't have any logging.
64+
static BCLog::Logger& GlobalLogger()
65+
{
66+
static BCLog::Logger g_logger;
67+
return g_logger;
68+
}
69+
6470
bool is_valid_flag_combination(script_verify_flags flags)
6571
{
6672
if (flags & SCRIPT_VERIFY_CLEANSTACK && ~flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) return false;
@@ -226,10 +232,7 @@ btck_Warning cast_btck_warning(kernel::Warning warning)
226232
}
227233

228234
struct LoggingConnection {
229-
// Reference to global log instance. This could be replaced with a
230-
// per-connection instance (#30342) to give clients more granular control
231-
// over logging.
232-
BCLog::Logger& m_logger{LogInstance()};
235+
BCLog::Logger m_logger;
233236
std::unique_ptr<std::list<std::function<void(const std::string&)>>::iterator> m_connection;
234237
void* m_user_data;
235238
std::function<void(void* user_data)> m_deleter;
@@ -374,7 +377,7 @@ struct ContextOptions {
374377
class Context
375378
{
376379
public:
377-
BCLog::Logger* m_logger;
380+
BCLog::Logger& m_logger;
378381

379382
std::unique_ptr<kernel::Context> m_context;
380383

@@ -389,18 +392,16 @@ class Context
389392
std::shared_ptr<KernelValidationInterface> m_validation_interface;
390393

391394
Context(const ContextOptions* options, bool& sane)
392-
: m_logger{options && options->m_logger ? options->m_logger : nullptr},
395+
: m_logger{*(options && options->m_logger ? options->m_logger : &GlobalLogger())},
393396
m_context{std::make_unique<kernel::Context>()},
394397
m_interrupt{std::make_unique<util::SignalInterrupt>()}
395398
{
396-
if (!m_logger) {
397-
// For efficiency, disable logging globally instead of writing log
398-
// messages to temporary buffer if no log callbacks are connected.
399-
if (BCLog::Logger& logger{LogInstance()}; logger.NumConnections() == 0 && logger.Enabled()) {
400-
logger.DisableLogging();
401-
}
402-
} else if (!m_logger->StartLogging()) {
403-
throw std::runtime_error("Failed to start logging");
399+
if (m_logger.NumConnections() > 0) {
400+
if (!m_logger.StartLogging()) throw std::runtime_error("Failed to start logging");
401+
} else if (m_logger.Enabled()) {
402+
// For efficiency, disable logging instead of writing log messages
403+
// to temporary buffer if no log callbacks are connected.
404+
m_logger.DisableLogging();
404405
}
405406

406407
if (options) {

src/kernel/bitcoinkernel.h

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -746,9 +746,7 @@ BITCOINKERNEL_API void btck_transaction_output_destroy(btck_TransactionOutput* t
746746
///@{
747747

748748
/**
749-
* @brief Set some options for the logger. Currently, this changes global
750-
* settings and will override settings for all existing @ref
751-
* btck_LoggingConnection instances.
749+
* @brief Set some options for the logger.
752750
*
753751
* @param[in] logger Non-null.
754752
* @param[in] options Sets formatting options of the log messages.
@@ -758,9 +756,7 @@ BITCOINKERNEL_API void btck_logging_set_options(btck_LoggingConnection* logger,
758756
/**
759757
* @brief Set the log level of the logger. This does not
760758
* enable the selected categories. Use @ref btck_logging_enable_category to
761-
* start logging from a specific, or all categories. Currently, this changes a global
762-
* setting and will override settings for all existing
763-
* @ref btck_LoggingConnection instances.
759+
* start logging from a specific, or all categories.
764760
*
765761
* @param[in] logger Non-null.
766762
* @param[in] category If btck_LogCategory_ALL is chosen, sets both the global fallback log level
@@ -774,19 +770,15 @@ BITCOINKERNEL_API void btck_logging_set_options(btck_LoggingConnection* logger,
774770
BITCOINKERNEL_API void btck_logging_set_level_category(btck_LoggingConnection* logger, btck_LogCategory category, btck_LogLevel level) BITCOINKERNEL_ARG_NONNULL(1);
775771

776772
/**
777-
* @brief Enable a specific log category for the logger. Currently, this
778-
* changes a global setting and will override settings for all existing @ref
779-
* btck_LoggingConnection instances.
773+
* @brief Enable a specific log category for the logger.
780774
*
781775
* @param[in] logger Non-null.
782776
* @param[in] category If btck_LogCategory_ALL is chosen, all categories will be enabled.
783777
*/
784778
BITCOINKERNEL_API void btck_logging_enable_category(btck_LoggingConnection* logger, btck_LogCategory category) BITCOINKERNEL_ARG_NONNULL(1);
785779

786780
/**
787-
* @brief Disable a specific log category for the logger. Currently, this
788-
* changes a global setting and will override settings for all existing @ref
789-
* btck_LoggingConnection instances.
781+
* @brief Disable a specific log category for the logger.
790782
*
791783
* @param[in] logger Non-null.
792784
* @param[in] category If btck_LogCategory_ALL is chosen, all categories will be disabled.
@@ -800,10 +792,6 @@ BITCOINKERNEL_API void btck_logging_disable_category(btck_LoggingConnection* log
800792
* log options and @ref btck_context_options_set_logger to receive log messages
801793
* generated in a particular context.
802794
*
803-
* Currently, most log state is global, so log options applied to other streams
804-
* may effect this stream, and if there are multiple contexts, log messages from
805-
* other contexts may be received. These behaviors can be improved internally.
806-
*
807795
* @param[in] log_callback Non-null, function through which messages will be logged.
808796
* @param[in] user_data Nullable, holds a user-defined opaque structure. Is passed back
809797
* to the user through the callback. If the user_data_destroy_callback

src/logging.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ using util::RemovePrefixView;
2323
const char * const DEFAULT_DEBUGLOGFILE = "debug.log";
2424
constexpr auto MAX_USER_SETABLE_SEVERITY_LEVEL{BCLog::Level::Info};
2525

26-
BCLog::Logger& LogInstance()
27-
{
26+
bool fLogIPs = DEFAULT_LOGIPS;
27+
28+
namespace BCLog {
2829
/**
2930
* NOTE: the logger instances is leaked on exit. This is ugly, but will be
3031
* cleaned up by the OS/libc. Defining a logger as a global object doesn't work
@@ -40,17 +41,29 @@ BCLog::Logger& LogInstance()
4041
* This method of initialization was originally introduced in
4142
* ee3374234c60aba2cc4c5cd5cac1c0aefc2d817c.
4243
*/
43-
static BCLog::Logger* g_logger{new BCLog::Logger()};
44-
return *g_logger;
45-
}
46-
47-
bool fLogIPs = DEFAULT_LOGIPS;
44+
Logger* g_logger{nullptr};
45+
} // namespace BCLog
4846

4947
static int FileWriteStr(std::string_view str, FILE *fp)
5048
{
5149
return fwrite(str.data(), 1, str.size(), fp);
5250
}
5351

52+
BCLog::Logger& LogInstance()
53+
{
54+
return *Assert(BCLog::g_logger);
55+
}
56+
57+
BCLog::Logger::Logger()
58+
{
59+
if (!g_logger) g_logger = this;
60+
}
61+
62+
BCLog::Logger::~Logger()
63+
{
64+
if (g_logger == this) g_logger = nullptr;
65+
}
66+
5467
bool BCLog::Logger::StartLogging()
5568
{
5669
StdLockGuard scoped_lock(m_cs);

src/logging.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ namespace BCLog {
185185
fs::path m_file_path;
186186
std::atomic<bool> m_reopen_file{false};
187187

188+
Logger();
189+
~Logger();
190+
188191
/** Send a string to the log output */
189192
void LogPrintStr(std::string_view str, SourceLocation&& source_loc, BCLog::LogFlags category, BCLog::Level level, bool should_ratelimit)
190193
EXCLUSIVE_LOCKS_REQUIRED(!m_cs);

0 commit comments

Comments
 (0)