ipc, refactor: Drop connect/listen/serve exe_name parameters
What changed, and why it matters
This is a straightforward internal code cleanup in Bitcoin Core's inter-process communication (IPC) layer. It moves the executable name parameter from individual connect/listen/serve methods into the protocol object's constructor. The executable name is only used for logging and debugging to tell different processes apart. There is no change to security-sensitive behavior, no bug fix, and no externally reported issue.
No security action required. Treat as normal refactoring review.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit refactors the ipc::Protocol interface and its Cap’n Proto implementation. Previously, connect(), listen(), and serve() each took a const char* exe_name argument; now the exe_name is stored as a member m_exe_name initialized in the CapnpProtocol constructor and MakeCapnpProtocol(exe_name). All call sites in src/ipc/interfaces.cpp and tests are updated accordingly. The values are passed to mp::ThreadName and mp::EventLoop for logging/thread-naming only. No logic, parsing, privilege handling, or IPC security semantics are altered.
Changed components
src/ipc/capnp/protocol.cppsrc/ipc/capnp/protocol.hsrc/ipc/interfaces.cppsrc/ipc/protocol.hsrc/ipc/test/ipc_tests.cppInspect captured patch +27 / −25
diff --git a/src/ipc/capnp/protocol.cpp b/src/ipc/capnp/protocol.cpp
index e39c5039..7fc893fc 100644
--- a/src/ipc/capnp/protocol.cpp
+++ b/src/ipc/capnp/protocol.cpp
@@ -71,34 +71,35 @@ void IpcLogFn(mp::LogMessage message)
class CapnpProtocol : public Protocol
{
public:
+ CapnpProtocol(const char* exe_name) : m_exe_name{exe_name} {}
~CapnpProtocol() noexcept(true)
{
m_loop_ref.reset();
if (m_loop_thread.joinable()) m_loop_thread.join();
assert(!m_loop);
};
- std::unique_ptr<interfaces::Init> connect(int fd, const char* exe_name) override
+ std::unique_ptr<interfaces::Init> connect(int fd) override
{
- startLoop(exe_name);
+ startLoop();
return mp::ConnectStream<messages::Init>(*m_loop, fd);
}
- void listen(int listen_fd, const char* exe_name, interfaces::Init& init) override
+ void listen(int listen_fd, interfaces::Init& init) override
{
- startLoop(exe_name);
+ startLoop();
if (::listen(listen_fd, /*backlog=*/5) != 0) {
throw std::system_error(errno, std::system_category());
}
mp::ListenConnections<messages::Init>(*m_loop, listen_fd, init);
}
- void serve(int fd, const char* exe_name, interfaces::Init& init, const std::function<void()>& ready_fn = {}) override
+ void serve(int fd, interfaces::Init& init, const std::function<void()>& ready_fn = {}) override
{
assert(!m_loop);
- mp::g_thread_context.thread_name = mp::ThreadName(exe_name);
+ mp::g_thread_context.thread_name = mp::ThreadName(m_exe_name);
mp::LogOptions opts = {
.log_fn = IpcLogFn,
.log_level = GetRequestedIPCLogLevel()
};
- m_loop.emplace(exe_name, std::move(opts), &m_context);
+ m_loop.emplace(m_exe_name, std::move(opts), &m_context);
if (ready_fn) ready_fn();
mp::ServeStream<messages::Init>(*m_loop, fd, init);
m_parent_connection = &m_loop->m_incoming_connections.back();
@@ -120,7 +121,7 @@ public:
mp::ProxyTypeRegister::types().at(type)(iface).cleanup_fns.emplace_back(std::move(cleanup));
}
Context& context() override { return m_context; }
- void startLoop(const char* exe_name)
+ void startLoop()
{
if (m_loop) return;
std::promise<void> promise;
@@ -130,7 +131,7 @@ public:
.log_fn = IpcLogFn,
.log_level = GetRequestedIPCLogLevel()
};
- m_loop.emplace(exe_name, std::move(opts), &m_context);
+ m_loop.emplace(m_exe_name, std::move(opts), &m_context);
m_loop_ref.emplace(*m_loop);
promise.set_value();
m_loop->loop();
@@ -138,6 +139,7 @@ public:
});
promise.get_future().wait();
}
+ const char* m_exe_name;
Context m_context;
std::thread m_loop_thread;
//! EventLoop object which manages I/O events for all connections.
@@ -151,6 +153,6 @@ public:
};
} // namespace
-std::unique_ptr<Protocol> MakeCapnpProtocol() { return std::make_unique<CapnpProtocol>(); }
+std::unique_ptr<Protocol> MakeCapnpProtocol(const char* exe_name) { return std::make_unique<CapnpProtocol>(exe_name); }
} // namespace capnp
} // namespace ipc
diff --git a/src/ipc/capnp/protocol.h b/src/ipc/capnp/protocol.h
index 54a8ae6e..ef828cd4 100644
--- a/src/ipc/capnp/protocol.h
+++ b/src/ipc/capnp/protocol.h
@@ -10,7 +10,7 @@
namespace ipc {
class Protocol;
namespace capnp {
-std::unique_ptr<Protocol> MakeCapnpProtocol();
+std::unique_ptr<Protocol> MakeCapnpProtocol(const char* exe_name);
} // namespace capnp
} // namespace ipc
diff --git a/src/ipc/interfaces.cpp b/src/ipc/interfaces.cpp
index 32febd35..3345a921 100644
--- a/src/ipc/interfaces.cpp
+++ b/src/ipc/interfaces.cpp
@@ -54,7 +54,7 @@ class IpcImpl : public interfaces::Ipc
public:
IpcImpl(const char* exe_name, const char* process_argv0, interfaces::Init& init)
: m_exe_name(exe_name), m_process_argv0(process_argv0), m_init(init),
- m_protocol(ipc::capnp::MakeCapnpProtocol()), m_process(ipc::MakeProcess())
+ m_protocol(ipc::capnp::MakeCapnpProtocol(exe_name)), m_process(ipc::MakeProcess())
{
}
std::unique_ptr<interfaces::Init> spawnProcess(const char* new_exe_name) override
@@ -62,7 +62,7 @@ public:
int pid;
int fd = m_process->spawn(new_exe_name, m_process_argv0, pid);
LogDebug(::BCLog::IPC, "Process %s pid %i launched\n", new_exe_name, pid);
- auto init = m_protocol->connect(fd, m_exe_name);
+ auto init = m_protocol->connect(fd);
Ipc::addCleanup(*init, [this, new_exe_name, pid] {
int status = m_process->waitSpawned(pid);
LogDebug(::BCLog::IPC, "Process %s pid %i exited with status %i\n", new_exe_name, pid, status);
@@ -77,7 +77,7 @@ public:
return false;
}
IgnoreCtrlC(strprintf("[%s] SIGINT received — waiting for parent to shut down.\n", m_exe_name));
- m_protocol->serve(fd, m_exe_name, m_init);
+ m_protocol->serve(fd, m_init);
exit_status = EXIT_SUCCESS;
return true;
}
@@ -106,12 +106,12 @@ public:
} else {
fd = m_process->connect(gArgs.GetDataDirNet(), "bitcoin-node", address);
}
- return m_protocol->connect(fd, m_exe_name);
+ return m_protocol->connect(fd);
}
void listenAddress(std::string& address) override
{
int fd = m_process->bind(gArgs.GetDataDirNet(), m_exe_name, address);
- m_protocol->listen(fd, m_exe_name, m_init);
+ m_protocol->listen(fd, m_init);
}
void disconnectIncoming() override
{
diff --git a/src/ipc/protocol.h b/src/ipc/protocol.h
index e7d66887..d14c7f20 100644
--- a/src/ipc/protocol.h
+++ b/src/ipc/protocol.h
@@ -32,12 +32,12 @@ public:
//! up its own state (calling ProxyServer destructors, etc) on disconnect,
//! and any client calls will just throw ipc::Exception errors after a
//! disconnect.
- virtual std::unique_ptr<interfaces::Init> connect(int fd, const char* exe_name) = 0;
+ virtual std::unique_ptr<interfaces::Init> connect(int fd) = 0;
//! Listen for connections on provided socket descriptor, accept them, and
//! handle requests on accepted connections. This method doesn't block, and
//! performs I/O on a background thread.
- virtual void listen(int listen_fd, const char* exe_name, interfaces::Init& init) = 0;
+ virtual void listen(int listen_fd, interfaces::Init& init) = 0;
//! Handle requests on provided socket descriptor, forwarding them to the
//! provided Init interface. Socket communication is handled on the
@@ -56,7 +56,7 @@ public:
//! client connections from another thread as soon as the event loop is
//! available, but should not be necessary in normal code which starts
//! clients and servers independently.
- virtual void serve(int fd, const char* exe_name, interfaces::Init& init, const std::function<void()>& ready_fn = {}) = 0;
+ virtual void serve(int fd, interfaces::Init& init, const std::function<void()>& ready_fn = {}) = 0;
//! Disconnect any incoming connections that are still connected.
virtual void disconnectIncoming() = 0;
diff --git a/src/ipc/test/ipc_tests.cpp b/src/ipc/test/ipc_tests.cpp
index b2617920..75b9544a 100644
--- a/src/ipc/test/ipc_tests.cpp
+++ b/src/ipc/test/ipc_tests.cpp
@@ -132,13 +132,13 @@ void IpcSocketPairTest()
int fds[2];
BOOST_CHECK_EQUAL(socketpair(AF_UNIX, SOCK_STREAM, 0, fds), 0);
std::unique_ptr<interfaces::Init> init{std::make_unique<TestInit>()};
- std::unique_ptr<ipc::Protocol> protocol{ipc::capnp::MakeCapnpProtocol()};
+ std::unique_ptr<ipc::Protocol> protocol{ipc::capnp::MakeCapnpProtocol("IpcSocketPairTest")};
std::promise<void> promise;
std::thread thread([&]() {
- protocol->serve(fds[0], "test-serve", *init, [&] { promise.set_value(); });
+ protocol->serve(fds[0], *init, [&] { promise.set_value(); });
});
promise.get_future().wait();
- std::unique_ptr<interfaces::Init> remote_init{protocol->connect(fds[1], "test-connect")};
+ std::unique_ptr<interfaces::Init> remote_init{protocol->connect(fds[1])};
std::unique_ptr<interfaces::Echo> remote_echo{remote_init->makeEcho()};
BOOST_CHECK_EQUAL(remote_echo->echo("echo test"), "echo test");
remote_echo.reset();
@@ -150,7 +150,7 @@ void IpcSocketPairTest()
void IpcSocketTest(const fs::path& datadir)
{
std::unique_ptr<interfaces::Init> init{std::make_unique<TestInit>()};
- std::unique_ptr<ipc::Protocol> protocol{ipc::capnp::MakeCapnpProtocol()};
+ std::unique_ptr<ipc::Protocol> protocol{ipc::capnp::MakeCapnpProtocol("IpcSocketTest")};
std::unique_ptr<ipc::Process> process{ipc::MakeProcess()};
std::string invalid_bind{"invalid:"};
@@ -162,14 +162,14 @@ void IpcSocketTest(const fs::path& datadir)
int serve_fd = process->bind(datadir, "test_bitcoin", address);
BOOST_CHECK_GE(serve_fd, 0);
BOOST_CHECK_EQUAL(address, bind_address);
- protocol->listen(serve_fd, "test-serve", *init);
+ protocol->listen(serve_fd, *init);
}};
auto connect_and_test{[&](const std::string& connect_address) {
std::string address{connect_address};
int connect_fd{process->connect(datadir, "test_bitcoin", address)};
BOOST_CHECK_EQUAL(address, connect_address);
- std::unique_ptr<interfaces::Init> remote_init{protocol->connect(connect_fd, "test-connect")};
+ std::unique_ptr<interfaces::Init> remote_init{protocol->connect(connect_fd)};
std::unique_ptr<interfaces::Echo> remote_echo{remote_init->makeEcho()};
BOOST_CHECK_EQUAL(remote_echo->echo("echo test"), "echo test");
}};
Why this scored 15/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.