multiprocess: align our logging with libmultiprocess's
What changed, and why it matters
This commit is a performance improvement, not a security fix. It changes how Bitcoin Core's multiprocess mode handles log messages coming from the libmultiprocess library. Previously, all libmultiprocess log messages were processed through expensive serialization even when they would be discarded. Now, Bitcoin Core tells libmultiprocess which log levels it actually cares about, so unneeded messages are skipped earlier, reducing CPU usage. There is no indication this change fixes a vulnerability or security bug.
No security action required. Treat as routine performance optimization. If reviewing for release notes, note it as a multiprocess logging/CPU usage improvement.
Security signals we found
No security-relevant signals in commit message or diff
Performance optimization only
No input validation, memory safety, authentication, or authorization changes
No bug fix or vulnerability remediation described
Evidence from the diff
The patch modifies src/ipc/capnp/protocol.cpp to add log-level filtering for libmultiprocess (mp) IPC logging. It introduces ConvertIPCLogLevel() to map mp::Log levels to BCLog::Level, and GetRequestedIPCLogLevel() to determine the minimum mp log level based on Bitcoin Core’s current IPC log category settings. The IpcLogFn callback now uses LogPrintLevel with the mapped level instead of always logging at debug level. The mp::LogOptions struct passed when initializing the mp event loop now includes a .log_level field set to GetRequestedIPCLogLevel(). This avoids libmultiprocess serializing log messages that Bitcoin Core would discard anyway.
Changed components
src/ipc/capnp/protocol.cppBitcoin Core multiprocess IPC loggingInspect captured patch +29 / −1
diff --git a/src/ipc/capnp/protocol.cpp b/src/ipc/capnp/protocol.cpp
index 4263aebd..27ef73e8 100644
--- a/src/ipc/capnp/protocol.cpp
+++ b/src/ipc/capnp/protocol.cpp
@@ -30,9 +30,35 @@
namespace ipc {
namespace capnp {
namespace {
+
+BCLog::Level ConvertIPCLogLevel(mp::Log level)
+{
+ switch (level) {
+ case mp::Log::Trace: return BCLog::Level::Trace;
+ case mp::Log::Debug: return BCLog::Level::Debug;
+ case mp::Log::Info: return BCLog::Level::Info;
+ case mp::Log::Warning: return BCLog::Level::Warning;
+ case mp::Log::Error: return BCLog::Level::Error;
+ case mp::Log::Raise: return BCLog::Level::Error;
+ } // no default case, so the compiler can warn about missing cases
+
+ // Be conservative and assume that if MP ever adds a new log level, it
+ // should only be shown at our most verbose level.
+ return BCLog::Level::Trace;
+}
+
+mp::Log GetRequestedIPCLogLevel()
+{
+ if (LogAcceptCategory(BCLog::IPC, BCLog::Level::Trace)) return mp::Log::Trace;
+ if (LogAcceptCategory(BCLog::IPC, BCLog::Level::Debug)) return mp::Log::Debug;
+
+ // Info, Warning, and Error are logged unconditionally
+ return mp::Log::Info;
+}
+
void IpcLogFn(mp::LogMessage message)
{
- LogDebug(BCLog::IPC, "%s\n", message.message);
+ LogPrintLevel(BCLog::IPC, ConvertIPCLogLevel(message.level), "%s\n", message.message);
if (message.level == mp::Log::Raise) throw Exception(message.message);
}
@@ -64,6 +90,7 @@ public:
mp::g_thread_context.thread_name = mp::ThreadName(exe_name);
mp::LogOptions opts = {
.log_fn = IpcLogFn,
+ .log_level = GetRequestedIPCLogLevel()
};
m_loop.emplace(exe_name, std::move(opts), &m_context);
if (ready_fn) ready_fn();
@@ -95,6 +122,7 @@ public:
util::ThreadRename("capnp-loop");
mp::LogOptions opts = {
.log_fn = IpcLogFn,
+ .log_level = GetRequestedIPCLogLevel()
};
m_loop.emplace(exe_name, std::move(opts), &m_context);
m_loop_ref.emplace(*m_loop);
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.