Skip to content

Commit

Permalink
multiprocess: Add bitcoin-node process spawning support
Browse files Browse the repository at this point in the history
Add bitcoin-node startup code to let it spawn and be spawned by other
processes
  • Loading branch information
ryanofsky committed Apr 23, 2021
1 parent 10afdf0 commit ddf7ecc
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 6 deletions.
3 changes: 3 additions & 0 deletions build_msvc/bitcoind/bitcoind.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down
4 changes: 2 additions & 2 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
15 changes: 11 additions & 4 deletions src/bitcoind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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);
}
43 changes: 43 additions & 0 deletions src/init/bitcoin-node.cpp
Original file line number Diff line number Diff line change
@@ -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
29 changes: 29 additions & 0 deletions src/init/bitcoind.cpp
Original file line number Diff line number Diff line change
@@ -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
14 changes: 14 additions & 0 deletions src/interfaces/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ class Init
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
3 changes: 3 additions & 0 deletions src/node/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class PeerManager;
namespace interfaces {
class Chain;
class ChainClient;
class Init;
class WalletClient;
} // namespace interfaces

Expand All @@ -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;
Expand Down

0 comments on commit ddf7ecc

Please sign in to comment.