From 2d3f72fd3fa45ab4e399094c39bfa93bb5a87323 Mon Sep 17 00:00:00 2001 From: Ryan Ofsky Date: Fri, 17 Jul 2026 08:28:00 -0400 Subject: [PATCH] ipc, refactor: Update mp::SpawnProcess call Use new SpawnProcess and StartSpawned functions to be compatible with an upcoming version of libmultiprocess which adds windows support. --- src/ipc/interfaces.cpp | 5 ++--- src/ipc/process.cpp | 14 +++++++------- src/ipc/process.h | 2 +- src/ipc/util.h | 18 ++++++++++++++++++ 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/ipc/interfaces.cpp b/src/ipc/interfaces.cpp index 75a854c2b70..40cddb4b662 100644 --- a/src/ipc/interfaces.cpp +++ b/src/ipc/interfaces.cpp @@ -62,10 +62,9 @@ public: } std::unique_ptr spawnProcess(const char* new_exe_name) override { - mp::ProcessId pid; - mp::SocketId fd = m_process->spawn(new_exe_name, m_process_argv0, pid); + const auto [pid, socket] = m_process->spawn(new_exe_name, m_process_argv0); LogDebug(::BCLog::IPC, "Process %s pid %i launched\n", new_exe_name, pid); - auto init = m_protocol->connect(m_protocol->makeStream(fd)); + auto init = m_protocol->connect(m_protocol->makeStream(socket)); 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); diff --git a/src/ipc/process.cpp b/src/ipc/process.cpp index d7f040780d5..a9aa47aedbc 100644 --- a/src/ipc/process.cpp +++ b/src/ipc/process.cpp @@ -32,13 +32,13 @@ namespace { class ProcessImpl : public Process { public: - mp::SocketId spawn(const std::string& new_exe_name, const fs::path& argv0_path, mp::ProcessId& pid) override + std::tuple spawn(const std::string& new_exe_name, const fs::path& argv0_path) override { - return mp::SpawnProcess(pid, [&](int fd) { + return mp::SpawnProcess([&](std::string connect_info) { fs::path path = argv0_path; path.remove_filename(); path /= fs::PathFromString(new_exe_name); - return std::vector{fs::PathToString(path), "-ipcfd", strprintf("%i", fd)}; + return std::vector{fs::PathToString(path), "-ipcfd", std::move(connect_info)}; }); } int waitSpawned(mp::ProcessId pid) override { return mp::WaitProcess(pid); } @@ -56,11 +56,11 @@ public: // in combination with other arguments because the parent process // should be able to control the child process through the IPC protocol // without passing information out of band. - const auto maybe_fd{ToIntegral(argv[2])}; - if (!maybe_fd) { - throw std::runtime_error(strprintf("Invalid -ipcfd number '%s'", argv[2])); + try { + socket = mp::StartSpawned(argv[2]); + } catch (const std::exception& e) { + throw std::runtime_error(strprintf("Invalid -ipcfd number '%s' (%s)", argv[2], e.what())); } - socket = *maybe_fd; return true; } mp::SocketId connect(const fs::path& data_dir, diff --git a/src/ipc/process.h b/src/ipc/process.h index 54ca204cd55..ac597cb042d 100644 --- a/src/ipc/process.h +++ b/src/ipc/process.h @@ -25,7 +25,7 @@ public: virtual ~Process() = default; //! Spawn process and return socket id for communicating with it. - virtual mp::SocketId spawn(const std::string& new_exe_name, const fs::path& argv0_path, mp::ProcessId& pid) = 0; + virtual std::tuple spawn(const std::string& new_exe_name, const fs::path& argv0_path) = 0; //! Wait for spawned process to exit and return its exit code. virtual int waitSpawned(mp::ProcessId pid) = 0; diff --git a/src/ipc/util.h b/src/ipc/util.h index ec36b418c71..3fd3ff160f3 100644 --- a/src/ipc/util.h +++ b/src/ipc/util.h @@ -5,8 +5,12 @@ #ifndef BITCOIN_IPC_UTIL_H #define BITCOIN_IPC_UTIL_H +#include +#include + #include #include +#include #include #include #include @@ -34,6 +38,20 @@ inline std::array SocketPair() KJ_SYSCALL(socketpair(AF_UNIX, SOCK_STREAM, 0, pair)); return {pair[0], pair[1]}; } + +inline std::tuple SpawnProcess(const std::function(std::string)>& spawn_argv) +{ + ProcessId pid; + SocketId socket = SpawnProcess(pid, [&](int fd) { return spawn_argv(strprintf("%d", fd)); }); + return {pid, socket}; +} + +inline SocketId StartSpawned(const std::string& connect_info) +{ + auto socket = ToIntegral(connect_info); + if (!socket) throw std::invalid_argument(strprintf("Invalid socket descriptor '%s'", connect_info)); + return *socket; +} #endif } // namespace mp