diff --git a/src/Makefile.am b/src/Makefile.am index e2ed70556d..93e059bc5e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -840,9 +840,11 @@ EXTRA_DIST += $(libbitcoin_ipc_mpgen_input) if BUILD_MULTIPROCESS LIBBITCOIN_IPC=libbitcoin_ipc.a libbitcoin_ipc_a_SOURCES = \ + ipc/capnp/context.h \ ipc/capnp/init-types.h \ ipc/capnp/protocol.cpp \ ipc/capnp/protocol.h \ + ipc/context.h \ ipc/exception.h \ ipc/interfaces.cpp \ ipc/process.cpp \ diff --git a/src/interfaces/ipc.h b/src/interfaces/ipc.h index e9e6c78053..963649fc9a 100644 --- a/src/interfaces/ipc.h +++ b/src/interfaces/ipc.h @@ -9,6 +9,10 @@ #include #include +namespace ipc { +struct Context; +} // namespace ipc + namespace interfaces { class Init; @@ -58,6 +62,9 @@ public: addCleanup(typeid(Interface), &iface, std::move(cleanup)); } + //! IPC context struct accessor (see struct definition for more description). + virtual ipc::Context& context() = 0; + protected: //! Internal implementation of public addCleanup method (above) as a //! type-erased virtual function, since template functions can't be virtual. diff --git a/src/ipc/capnp/context.h b/src/ipc/capnp/context.h new file mode 100644 index 0000000000..06e1614494 --- /dev/null +++ b/src/ipc/capnp/context.h @@ -0,0 +1,23 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_IPC_CAPNP_CONTEXT_H +#define BITCOIN_IPC_CAPNP_CONTEXT_H + +#include + +namespace ipc { +namespace capnp { +//! Cap'n Proto context struct. Generally the parent ipc::Context struct should +//! be used instead of this struct to give all IPC protocols access to +//! application state, so there aren't unnecessary differences between IPC +//! protocols. But this specialized struct can be used to pass capnp-specific +//! function and object types to capnp hooks. +struct Context : ipc::Context +{ +}; +} // namespace capnp +} // namespace ipc + +#endif // BITCOIN_IPC_CAPNP_CONTEXT_H diff --git a/src/ipc/capnp/protocol.cpp b/src/ipc/capnp/protocol.cpp index 74c66c899a..37b57a9525 100644 --- a/src/ipc/capnp/protocol.cpp +++ b/src/ipc/capnp/protocol.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include +#include #include #include #include @@ -54,7 +55,7 @@ public: { assert(!m_loop); mp::g_thread_context.thread_name = mp::ThreadName(exe_name); - m_loop.emplace(exe_name, &IpcLogFn, nullptr); + m_loop.emplace(exe_name, &IpcLogFn, &m_context); mp::ServeStream(*m_loop, fd, init); m_loop->loop(); m_loop.reset(); @@ -63,13 +64,14 @@ public: { mp::ProxyTypeRegister::types().at(type)(iface).cleanup.emplace_back(std::move(cleanup)); } + Context& context() override { return m_context; } void startLoop(const char* exe_name) { if (m_loop) return; std::promise promise; m_loop_thread = std::thread([&] { util::ThreadRename("capnp-loop"); - m_loop.emplace(exe_name, &IpcLogFn, nullptr); + m_loop.emplace(exe_name, &IpcLogFn, &m_context); { std::unique_lock lock(m_loop->m_mutex); m_loop->addClient(lock); @@ -80,6 +82,7 @@ public: }); promise.get_future().wait(); } + Context m_context; std::thread m_loop_thread; std::optional m_loop; }; diff --git a/src/ipc/context.h b/src/ipc/context.h new file mode 100644 index 0000000000..924d7d7450 --- /dev/null +++ b/src/ipc/context.h @@ -0,0 +1,19 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_IPC_CONTEXT_H +#define BITCOIN_IPC_CONTEXT_H + +namespace ipc { +//! Context struct used to give IPC protocol implementations or implementation +//! hooks access to application state, in case they need to run extra code that +//! isn't needed within a single process, like code copying global state from an +//! existing process to a new process when it's initialized, or code dealing +//! with shared objects that are created or destroyed remotely. +struct Context +{ +}; +} // namespace ipc + +#endif // BITCOIN_IPC_CONTEXT_H diff --git a/src/ipc/interfaces.cpp b/src/ipc/interfaces.cpp index ad4b78ed81..580590fde9 100644 --- a/src/ipc/interfaces.cpp +++ b/src/ipc/interfaces.cpp @@ -60,6 +60,7 @@ public: { m_protocol->addCleanup(type, iface, std::move(cleanup)); } + Context& context() override { return m_protocol->context(); } const char* m_exe_name; const char* m_process_argv0; interfaces::Init& m_init; diff --git a/src/ipc/protocol.h b/src/ipc/protocol.h index af955b0007..4cd892e411 100644 --- a/src/ipc/protocol.h +++ b/src/ipc/protocol.h @@ -12,6 +12,8 @@ #include namespace ipc { +struct Context; + //! IPC protocol interface for calling IPC methods over sockets. //! //! There may be different implementations of this interface for different IPC @@ -33,6 +35,9 @@ public: //! Add cleanup callback to interface that will run when the interface is //! deleted. virtual void addCleanup(std::type_index type, void* iface, std::function cleanup) = 0; + + //! Context accessor. + virtual Context& context() = 0; }; } // namespace ipc