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.
This commit is contained in:
Ryan Ofsky
2026-07-17 08:28:00 -04:00
parent e9f19815ca
commit 2d3f72fd3f
4 changed files with 28 additions and 11 deletions

View File

@@ -62,10 +62,9 @@ public:
}
std::unique_ptr<interfaces::Init> 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);

View File

@@ -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<mp::ProcessId, mp::SocketId> 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<std::string>{fs::PathToString(path), "-ipcfd", strprintf("%i", fd)};
return std::vector<std::string>{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<int32_t>(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,

View File

@@ -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<mp::ProcessId, mp::SocketId> 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;

View File

@@ -5,8 +5,12 @@
#ifndef BITCOIN_IPC_UTIL_H
#define BITCOIN_IPC_UTIL_H
#include <tinyformat.h>
#include <util/strencodings.h>
#include <array>
#include <cstdint>
#include <functional>
#include <kj/debug.h>
#include <mp/util.h>
#include <mp/version.h>
@@ -34,6 +38,20 @@ inline std::array<SocketId, 2> SocketPair()
KJ_SYSCALL(socketpair(AF_UNIX, SOCK_STREAM, 0, pair));
return {pair[0], pair[1]};
}
inline std::tuple<ProcessId, SocketId> SpawnProcess(const std::function<std::vector<std::string>(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<SocketId>(connect_info);
if (!socket) throw std::invalid_argument(strprintf("Invalid socket descriptor '%s'", connect_info));
return *socket;
}
#endif
} // namespace mp