Skip to content

Commit ddf7ecc

Browse files
committed
multiprocess: Add bitcoin-node process spawning support
Add bitcoin-node startup code to let it spawn and be spawned by other processes
1 parent 10afdf0 commit ddf7ecc

File tree

7 files changed

+105
-6
lines changed

7 files changed

+105
-6
lines changed

build_msvc/bitcoind/bitcoind.vcxproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
</PropertyGroup>
1111
<ItemGroup>
1212
<ClCompile Include="..\..\src\bitcoind.cpp" />
13+
<ClCompile Include="..\..\src\init\bitcoind.cpp">
14+
<ObjectFileName>$(IntDir)init_bitcoind.obj</ObjectFileName>
15+
</ClCompile>
1316
</ItemGroup>
1417
<ItemGroup>
1518
<ProjectReference Include="..\libbitcoinconsensus\libbitcoinconsensus.vcxproj">

src/Makefile.am

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -640,13 +640,13 @@ bitcoin_bin_ldadd = \
640640

641641
bitcoin_bin_ldadd += $(BOOST_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) $(SQLITE_LIBS)
642642

643-
bitcoind_SOURCES = $(bitcoin_daemon_sources)
643+
bitcoind_SOURCES = $(bitcoin_daemon_sources) init/bitcoind.cpp
644644
bitcoind_CPPFLAGS = $(bitcoin_bin_cppflags)
645645
bitcoind_CXXFLAGS = $(bitcoin_bin_cxxflags)
646646
bitcoind_LDFLAGS = $(bitcoin_bin_ldflags)
647647
bitcoind_LDADD = $(LIBBITCOIN_SERVER) $(bitcoin_bin_ldadd)
648648

649-
bitcoin_node_SOURCES = $(bitcoin_daemon_sources)
649+
bitcoin_node_SOURCES = $(bitcoin_daemon_sources) init/bitcoin-node.cpp
650650
bitcoin_node_CPPFLAGS = $(bitcoin_bin_cppflags)
651651
bitcoin_node_CXXFLAGS = $(bitcoin_bin_cxxflags)
652652
bitcoin_node_LDFLAGS = $(bitcoin_bin_ldflags)

src/bitcoind.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <compat.h>
1313
#include <init.h>
1414
#include <interfaces/chain.h>
15+
#include <interfaces/init.h>
1516
#include <node/context.h>
1617
#include <node/ui_interface.h>
1718
#include <noui.h>
@@ -104,10 +105,8 @@ int fork_daemon(bool nochdir, bool noclose, TokenPipeEnd& endpoint)
104105

105106
#endif
106107

107-
static bool AppInit(int argc, char* argv[])
108+
static bool AppInit(NodeContext& node, int argc, char* argv[])
108109
{
109-
NodeContext node;
110-
111110
bool fRet = false;
112111

113112
util::ThreadSetInternalName("init");
@@ -254,10 +253,18 @@ int main(int argc, char* argv[])
254253
util::WinCmdLineArgs winArgs;
255254
std::tie(argc, argv) = winArgs.get();
256255
#endif
256+
257+
NodeContext node;
258+
int exit_status;
259+
std::unique_ptr<interfaces::Init> init = interfaces::MakeNodeInit(node, argc, argv, exit_status);
260+
if (!init) {
261+
return exit_status;
262+
}
263+
257264
SetupEnvironment();
258265

259266
// Connect bitcoind signal handlers
260267
noui_connect();
261268

262-
return (AppInit(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE);
269+
return (AppInit(node, argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE);
263270
}

src/init/bitcoin-node.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) 2021 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <interfaces/init.h>
6+
#include <interfaces/ipc.h>
7+
#include <node/context.h>
8+
9+
#include <memory>
10+
11+
namespace init {
12+
namespace {
13+
const char* EXE_NAME = "bitcoin-node";
14+
15+
class BitcoinNodeInit : public interfaces::Init
16+
{
17+
public:
18+
BitcoinNodeInit(NodeContext& node, const char* arg0)
19+
: m_node(node),
20+
m_ipc(interfaces::MakeIpc(EXE_NAME, arg0, *this))
21+
{
22+
m_node.init = this;
23+
}
24+
interfaces::Ipc* ipc() override { return m_ipc.get(); }
25+
NodeContext& m_node;
26+
std::unique_ptr<interfaces::Ipc> m_ipc;
27+
};
28+
} // namespace
29+
} // namespace init
30+
31+
namespace interfaces {
32+
std::unique_ptr<Init> MakeNodeInit(NodeContext& node, int argc, char* argv[], int& exit_status)
33+
{
34+
auto init = std::make_unique<init::BitcoinNodeInit>(node, argc > 0 ? argv[0] : "");
35+
// Check if bitcoin-node is being invoked as an IPC server. If so, then
36+
// bypass normal execution and just respond to requests over the IPC
37+
// channel and return null.
38+
if (init->m_ipc->startSpawnedProcess(argc, argv, exit_status)) {
39+
return nullptr;
40+
}
41+
return init;
42+
}
43+
} // namespace interfaces

src/init/bitcoind.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) 2021 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <interfaces/init.h>
6+
#include <node/context.h>
7+
8+
#include <memory>
9+
10+
namespace init {
11+
namespace {
12+
class BitcoindInit : public interfaces::Init
13+
{
14+
public:
15+
BitcoindInit(NodeContext& node) : m_node(node)
16+
{
17+
m_node.init = this;
18+
}
19+
NodeContext& m_node;
20+
};
21+
} // namespace
22+
} // namespace init
23+
24+
namespace interfaces {
25+
std::unique_ptr<Init> MakeNodeInit(NodeContext& node, int argc, char* argv[], int& exit_status)
26+
{
27+
return std::make_unique<init::BitcoindInit>(node);
28+
}
29+
} // namespace interfaces

src/interfaces/init.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,20 @@ class Init
3131
virtual std::unique_ptr<WalletClient> makeWalletClient(Chain& chain);
3232
virtual Ipc* ipc();
3333
};
34+
35+
//! Return implementation of Init interface for the node process. If the argv
36+
//! indicates that this is a child process spawned to handle requests from a
37+
//! parent process, this blocks and handles requests, then returns null and a
38+
//! status code to exit with. If this returns non-null, the caller can start up
39+
//! normally and use the Init object to spawn and connect to other processes
40+
//! while it is running.
41+
std::unique_ptr<Init> MakeNodeInit(NodeContext& node, int argc, char* argv[], int& exit_status);
42+
43+
//! Return implementation of Init interface for the wallet process.
44+
std::unique_ptr<Init> MakeWalletInit(int argc, char* argv[], int& exit_status);
45+
46+
//! Return implementation of Init interface for the gui process.
47+
std::unique_ptr<Init> MakeGuiInit(int argc, char* argv[]);
3448
} // namespace interfaces
3549

3650
#endif // BITCOIN_INTERFACES_INIT_H

src/node/context.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class PeerManager;
2222
namespace interfaces {
2323
class Chain;
2424
class ChainClient;
25+
class Init;
2526
class WalletClient;
2627
} // namespace interfaces
2728

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

0 commit comments

Comments
 (0)