Skip to content

Commit 31b29f8

Browse files
committed
Merge #33229: multiprocess: Don't require bitcoin -m argument when IPC options are used
453b0fa bitcoin: Make wrapper not require -m (Ryan Ofsky) 29e836f test: add tool_bitcoin to test bitcoin wrapper behavior (Ryan Ofsky) 0972f55 init: add exe name to bitcoind, bitcoin-node -version output to be able to distinguish these in tests (Ryan Ofsky) Pull request description: This change makes the `bitcoin` command respect IPC command line options and _bitcoin.conf_ settings, so IPC listening can be enabled by just running `bitcoin node -ipcbind=unix` or `bitcoin node` with `ipcbind=unix` in the configuration file, and there is no longer a need to specify a multiprocess `-m` option like `bitcoin -m node [...]` sipa and theuni in #31802 pointed out that users shouldn't be exposed to multiprocess implementation details just to use IPC features, so current need to specify the `bitcoin -m` option in conjunction with `-ipcbind` could be seen as a design mistake and not just a usage inconvenience. This PR also adds a dedicated functional test for the `bitcoin` wrapper command and to make sure it calls the right binaries and test the new functionality. --- This PR is part of the [process separation project](#28722). ACKs for top commit: Sjors: re-ACK 453b0fa achow101: ACK 453b0fa TheCharlatan: Re-ACK 453b0fa Tree-SHA512: 9e49cb7e183fd220fa7a4e8ac68cef55f3cb2ccec40ad2a9d3e3f31db64c4953db8337f8caf7fce877bc97002ae97568dcf47ee269a06ca1f503f119bfe392c1
2 parents e62e0a1 + 453b0fa commit 31b29f8

File tree

13 files changed

+174
-10
lines changed

13 files changed

+174
-10
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ if(BUILD_BITCOIN_BIN)
292292
add_executable(bitcoin bitcoin.cpp)
293293
add_windows_resources(bitcoin bitcoin-res.rc)
294294
add_windows_application_manifest(bitcoin)
295-
target_link_libraries(bitcoin core_interface bitcoin_util)
295+
target_link_libraries(bitcoin core_interface bitcoin_common bitcoin_util)
296296
install_binary_component(bitcoin HAS_MANPAGE)
297297
endif()
298298

src/bitcoin.cpp

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <bitcoin-build-config.h> // IWYU pragma: keep
66

77
#include <clientversion.h>
8+
#include <common/args.h>
89
#include <util/fs.h>
910
#include <util/exec.h>
1011
#include <util/strencodings.h>
@@ -47,14 +48,15 @@ Run '%s help' to see additional commands (e.g. for testing and debugging).
4748
)";
4849

4950
struct CommandLine {
50-
bool use_multiprocess{false};
51+
std::optional<bool> use_multiprocess;
5152
bool show_version{false};
5253
bool show_help{false};
5354
std::string_view command;
5455
std::vector<const char*> args;
5556
};
5657

5758
CommandLine ParseCommandLine(int argc, char* argv[]);
59+
bool UseMultiprocess(const CommandLine& cmd);
5860
static void ExecCommand(const std::vector<const char*>& args, std::string_view argv0);
5961

6062
int main(int argc, char* argv[])
@@ -78,9 +80,9 @@ int main(int argc, char* argv[])
7880
return EXIT_FAILURE;
7981
}
8082
} else if (cmd.command == "gui") {
81-
args.emplace_back(cmd.use_multiprocess ? "bitcoin-gui" : "bitcoin-qt");
83+
args.emplace_back(UseMultiprocess(cmd) ? "bitcoin-gui" : "bitcoin-qt");
8284
} else if (cmd.command == "node") {
83-
args.emplace_back(cmd.use_multiprocess ? "bitcoin-node" : "bitcoind");
85+
args.emplace_back(UseMultiprocess(cmd) ? "bitcoin-node" : "bitcoind");
8486
} else if (cmd.command == "rpc") {
8587
args.emplace_back("bitcoin-cli");
8688
// Since "bitcoin rpc" is a new interface that doesn't need to be
@@ -143,6 +145,30 @@ CommandLine ParseCommandLine(int argc, char* argv[])
143145
return cmd;
144146
}
145147

148+
bool UseMultiprocess(const CommandLine& cmd)
149+
{
150+
// If -m or -M options were explicitly specified, there is no need to
151+
// further parse arguments to determine which to use.
152+
if (cmd.use_multiprocess) return *cmd.use_multiprocess;
153+
154+
ArgsManager args;
155+
args.SetDefaultFlags(ArgsManager::ALLOW_ANY);
156+
std::string error_message;
157+
auto argv{cmd.args};
158+
argv.insert(argv.begin(), nullptr);
159+
if (!args.ParseParameters(argv.size(), argv.data(), error_message)) {
160+
tfm::format(std::cerr, "Warning: failed to parse subcommand command line options: %s\n", error_message);
161+
}
162+
if (!args.ReadConfigFiles(error_message, true)) {
163+
tfm::format(std::cerr, "Warning: failed to parse subcommand config: %s\n", error_message);
164+
}
165+
args.SelectConfigNetwork(args.GetChainTypeString());
166+
167+
// If any -ipc* options are set these need to be processed by a
168+
// multiprocess-capable binary.
169+
return args.IsArgSet("-ipcbind") || args.IsArgSet("-ipcconnect") || args.IsArgSet("-ipcfd");
170+
}
171+
146172
//! Execute the specified bitcoind, bitcoin-qt or other command line in `args`
147173
//! using src, bin and libexec directory paths relative to this executable, where
148174
//! the path to this executable is specified in `wrapper_argv0`.

src/bitcoind.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,16 @@ static bool ParseArgs(NodeContext& node, int argc, char* argv[])
132132
return true;
133133
}
134134

135-
static bool ProcessInitCommands(ArgsManager& args)
135+
static bool ProcessInitCommands(interfaces::Init& init, ArgsManager& args)
136136
{
137137
// Process help and version before taking care about datadir
138138
if (HelpRequested(args) || args.GetBoolArg("-version", false)) {
139-
std::string strUsage = CLIENT_NAME " daemon version " + FormatFullVersion() + "\n";
139+
std::string strUsage = CLIENT_NAME " daemon version " + FormatFullVersion();
140+
if (const char* exe_name{init.exeName()}) {
141+
strUsage += " ";
142+
strUsage += exe_name;
143+
}
144+
strUsage += "\n";
140145

141146
if (args.GetBoolArg("-version", false)) {
142147
strUsage += FormatParagraph(LicenseInfo());
@@ -277,7 +282,7 @@ MAIN_FUNCTION
277282
ArgsManager& args = *Assert(node.args);
278283
if (!ParseArgs(node, argc, argv)) return EXIT_FAILURE;
279284
// Process early info return commands such as -help or -version
280-
if (ProcessInitCommands(args)) return EXIT_SUCCESS;
285+
if (ProcessInitCommands(*init, args)) return EXIT_SUCCESS;
281286

282287
// Start application
283288
if (!AppInit(node) || !Assert(node.shutdown_signal)->wait()) {

src/common/args.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,13 @@ std::optional<unsigned int> ArgsManager::GetArgFlags(const std::string& name) co
266266
return search->second.m_flags;
267267
}
268268
}
269-
return std::nullopt;
269+
return m_default_flags;
270+
}
271+
272+
void ArgsManager::SetDefaultFlags(std::optional<unsigned int> flags)
273+
{
274+
LOCK(cs_args);
275+
m_default_flags = flags;
270276
}
271277

272278
fs::path ArgsManager::GetPathArg(std::string arg, const fs::path& default_value) const

src/common/args.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ class ArgsManager
137137
std::string m_network GUARDED_BY(cs_args);
138138
std::set<std::string> m_network_only_args GUARDED_BY(cs_args);
139139
std::map<OptionsCategory, std::map<std::string, Arg>> m_available_args GUARDED_BY(cs_args);
140+
std::optional<unsigned int> m_default_flags GUARDED_BY(cs_args){};
140141
bool m_accept_any_command GUARDED_BY(cs_args){true};
141142
std::list<SectionInfo> m_config_sections GUARDED_BY(cs_args);
142143
std::optional<fs::path> m_config_path GUARDED_BY(cs_args);
@@ -375,10 +376,15 @@ class ArgsManager
375376

376377
/**
377378
* Return Flags for known arg.
378-
* Return nullopt for unknown arg.
379+
* Return default flags for unknown arg.
379380
*/
380381
std::optional<unsigned int> GetArgFlags(const std::string& name) const;
381382

383+
/**
384+
* Set default flags to return for an unknown arg.
385+
*/
386+
void SetDefaultFlags(std::optional<unsigned int>);
387+
382388
/**
383389
* Get settings file path, or return false if read-write settings were
384390
* disabled with -nosettings.

src/init/bitcoin-gui.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class BitcoinGuiInit : public interfaces::Init
3939
// bitcoin-node accepts the option, and bitcoin-gui accepts all bitcoin-node
4040
// options and will start the node with those options.
4141
bool canListenIpc() override { return true; }
42+
const char* exeName() override { return EXE_NAME; }
4243
node::NodeContext m_node;
4344
std::unique_ptr<interfaces::Ipc> m_ipc;
4445
};

src/init/bitcoin-node.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class BitcoinNodeInit : public interfaces::Init
3838
std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
3939
interfaces::Ipc* ipc() override { return m_ipc.get(); }
4040
bool canListenIpc() override { return true; }
41+
const char* exeName() override { return EXE_NAME; }
4142
node::NodeContext& m_node;
4243
std::unique_ptr<interfaces::Ipc> m_ipc;
4344
};

src/init/bitcoin-qt.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
namespace init {
1818
namespace {
19+
const char* EXE_NAME = "bitcoin-qt";
20+
1921
class BitcoinQtInit : public interfaces::Init
2022
{
2123
public:
@@ -32,6 +34,7 @@ class BitcoinQtInit : public interfaces::Init
3234
return MakeWalletLoader(chain, *Assert(m_node.args));
3335
}
3436
std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
37+
const char* exeName() override { return EXE_NAME; }
3538
node::NodeContext m_node;
3639
};
3740
} // namespace

src/init/bitcoind.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ using node::NodeContext;
1818

1919
namespace init {
2020
namespace {
21+
const char* EXE_NAME = "bitcoind";
22+
2123
class BitcoindInit : public interfaces::Init
2224
{
2325
public:
@@ -34,6 +36,7 @@ class BitcoindInit : public interfaces::Init
3436
return MakeWalletLoader(chain, *Assert(m_node.args));
3537
}
3638
std::unique_ptr<interfaces::Echo> makeEcho() override { return interfaces::MakeEcho(); }
39+
const char* exeName() override { return EXE_NAME; }
3740
NodeContext& m_node;
3841
};
3942
} // namespace

src/interfaces/init.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class Init
3838
virtual std::unique_ptr<Echo> makeEcho() { return nullptr; }
3939
virtual Ipc* ipc() { return nullptr; }
4040
virtual bool canListenIpc() { return false; }
41+
virtual const char* exeName() { return nullptr; }
4142
};
4243

4344
//! Return implementation of Init interface for the node process. If the argv

0 commit comments

Comments
 (0)