multiprocess: Add bitcoin-node process spawning support

Add bitcoin-node startup code to let it spawn and be spawned by other
processes
pull/826/head
Russell Yanofsky 7 years ago
parent 10afdf0280
commit ddf7ecc8df

@ -10,6 +10,9 @@
</PropertyGroup>
<ItemGroup>
<ClCompile Include="..\..\src\bitcoind.cpp" />
<ClCompile Include="..\..\src\init\bitcoind.cpp">
<ObjectFileName>$(IntDir)init_bitcoind.obj</ObjectFileName>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\libbitcoinconsensus\libbitcoinconsensus.vcxproj">

@ -640,13 +640,13 @@ bitcoin_bin_ldadd = \
bitcoin_bin_ldadd += $(BOOST_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) $(SQLITE_LIBS)
bitcoind_SOURCES = $(bitcoin_daemon_sources)
bitcoind_SOURCES = $(bitcoin_daemon_sources) init/bitcoind.cpp
bitcoind_CPPFLAGS = $(bitcoin_bin_cppflags)
bitcoind_CXXFLAGS = $(bitcoin_bin_cxxflags)
bitcoind_LDFLAGS = $(bitcoin_bin_ldflags)
bitcoind_LDADD = $(LIBBITCOIN_SERVER) $(bitcoin_bin_ldadd)
bitcoin_node_SOURCES = $(bitcoin_daemon_sources)
bitcoin_node_SOURCES = $(bitcoin_daemon_sources) init/bitcoin-node.cpp
bitcoin_node_CPPFLAGS = $(bitcoin_bin_cppflags)
bitcoin_node_CXXFLAGS = $(bitcoin_bin_cxxflags)
bitcoin_node_LDFLAGS = $(bitcoin_bin_ldflags)

@ -12,6 +12,7 @@
#include <compat.h>
#include <init.h>
#include <interfaces/chain.h>
#include <interfaces/init.h>
#include <node/context.h>
#include <node/ui_interface.h>
#include <noui.h>
@ -104,10 +105,8 @@ int fork_daemon(bool nochdir, bool noclose, TokenPipeEnd& endpoint)
#endif
static bool AppInit(int argc, char* argv[])
static bool AppInit(NodeContext& node, int argc, char* argv[])
{
NodeContext node;
bool fRet = false;
util::ThreadSetInternalName("init");
@ -254,10 +253,18 @@ int main(int argc, char* argv[])
util::WinCmdLineArgs winArgs;
std::tie(argc, argv) = winArgs.get();
#endif
NodeContext node;
int exit_status;
std::unique_ptr<interfaces::Init> init = interfaces::MakeNodeInit(node, argc, argv, exit_status);
if (!init) {
return exit_status;
}
SetupEnvironment();
// Connect bitcoind signal handlers
noui_connect();
return (AppInit(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE);
return (AppInit(node, argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE);
}

@ -0,0 +1,43 @@
// 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.
#include <interfaces/init.h>
#include <interfaces/ipc.h>
#include <node/context.h>
#include <memory>
namespace init {
namespace {
const char* EXE_NAME = "bitcoin-node";
class BitcoinNodeInit : public interfaces::Init
{
public:
BitcoinNodeInit(NodeContext& node, const char* arg0)
: m_node(node),
m_ipc(interfaces::MakeIpc(EXE_NAME, arg0, *this))
{
m_node.init = this;
}
interfaces::Ipc* ipc() override { return m_ipc.get(); }
NodeContext& m_node;
std::unique_ptr<interfaces::Ipc> m_ipc;
};
} // namespace
} // namespace init
namespace interfaces {
std::unique_ptr<Init> MakeNodeInit(NodeContext& node, int argc, char* argv[], int& exit_status)
{
auto init = std::make_unique<init::BitcoinNodeInit>(node, argc > 0 ? argv[0] : "");
// Check if bitcoin-node is being invoked as an IPC server. If so, then
// bypass normal execution and just respond to requests over the IPC
// channel and return null.
if (init->m_ipc->startSpawnedProcess(argc, argv, exit_status)) {
return nullptr;
}
return init;
}
} // namespace interfaces

@ -0,0 +1,29 @@
// 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.
#include <interfaces/init.h>
#include <node/context.h>
#include <memory>
namespace init {
namespace {
class BitcoindInit : public interfaces::Init
{
public:
BitcoindInit(NodeContext& node) : m_node(node)
{
m_node.init = this;
}
NodeContext& m_node;
};
} // namespace
} // namespace init
namespace interfaces {
std::unique_ptr<Init> MakeNodeInit(NodeContext& node, int argc, char* argv[], int& exit_status)
{
return std::make_unique<init::BitcoindInit>(node);
}
} // namespace interfaces

@ -31,6 +31,20 @@ public:
virtual std::unique_ptr<WalletClient> makeWalletClient(Chain& chain);
virtual Ipc* ipc();
};
//! Return implementation of Init interface for the node process. If the argv
//! indicates that this is a child process spawned to handle requests from a
//! parent process, this blocks and handles requests, then returns null and a
//! status code to exit with. If this returns non-null, the caller can start up
//! normally and use the Init object to spawn and connect to other processes
//! while it is running.
std::unique_ptr<Init> MakeNodeInit(NodeContext& node, int argc, char* argv[], int& exit_status);
//! Return implementation of Init interface for the wallet process.
std::unique_ptr<Init> MakeWalletInit(int argc, char* argv[], int& exit_status);
//! Return implementation of Init interface for the gui process.
std::unique_ptr<Init> MakeGuiInit(int argc, char* argv[]);
} // namespace interfaces
#endif // BITCOIN_INTERFACES_INIT_H

@ -22,6 +22,7 @@ class PeerManager;
namespace interfaces {
class Chain;
class ChainClient;
class Init;
class WalletClient;
} // namespace interfaces
@ -36,6 +37,8 @@ class WalletClient;
//! any member functions. It should just be a collection of references that can
//! be used without pulling in unwanted dependencies or functionality.
struct NodeContext {
//! Init interface for initializing current process and connecting to other processes.
interfaces::Init* init{nullptr};
std::unique_ptr<CAddrMan> addrman;
std::unique_ptr<CConnman> connman;
std::unique_ptr<CTxMemPool> mempool;

Loading…
Cancel
Save