Skip to content

Commit eefe569

Browse files
ryanofskypinheadmz
andcommitted
bugfix: Fix incorrect debug.log config file path
Currently debug.log will show the wrong bitcoin.conf config file path when bitcoind is invoked without -conf or -datadir arguments, and there's a default bitcoin.conf file which specifies another datadir= location. When this happens, the debug.log will include an incorrect "Config file:" line referring to a bitcoin.conf file in the other datadir, instead of the referring to the actual configuration file in the default datadir which was parsed. The bad log print was reported and originally fixed in bitcoin/bitcoin#27303 by Matthew Zipkin <[email protected]> This PR takes a slightly different approach to fixing the bug, trying to avoid future bugs by not allowing the GetConfigFilePath function to be called before the the configuration is parsed, and deleting GetConfigFile function which could be confused with GetConfigFilePath. It also includes a test for the bug which the original fix did not have. Co-authored-by: Matthew Zipkin <[email protected]>
1 parent 3746f00 commit eefe569

File tree

6 files changed

+45
-9
lines changed

6 files changed

+45
-9
lines changed

src/common/args.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,8 @@ bool CheckDataDirOption(const ArgsManager& args)
714714

715715
fs::path ArgsManager::GetConfigFilePath() const
716716
{
717-
return GetConfigFile(*this, GetPathArg("-conf", BITCOIN_CONF_FILENAME));
717+
LOCK(cs_args);
718+
return *Assert(m_config_path);
718719
}
719720

720721
std::string ArgsManager::GetChainName() const

src/common/args.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ extern const char * const BITCOIN_SETTINGS_FILENAME;
2626

2727
// Return true if -datadir option points to a valid directory or is not specified.
2828
bool CheckDataDirOption(const ArgsManager& args);
29-
fs::path GetConfigFile(const ArgsManager& args, const fs::path& configuration_file_path);
3029

3130
/**
3231
* Most paths passed as configuration arguments are treated as relative to
@@ -136,6 +135,7 @@ class ArgsManager
136135
std::map<OptionsCategory, std::map<std::string, Arg>> m_available_args GUARDED_BY(cs_args);
137136
bool m_accept_any_command GUARDED_BY(cs_args){true};
138137
std::list<SectionInfo> m_config_sections GUARDED_BY(cs_args);
138+
std::optional<fs::path> m_config_path GUARDED_BY(cs_args);
139139
mutable fs::path m_cached_blocks_path GUARDED_BY(cs_args);
140140
mutable fs::path m_cached_datadir_path GUARDED_BY(cs_args);
141141
mutable fs::path m_cached_network_datadir_path GUARDED_BY(cs_args);

src/common/config.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,6 @@
2626
#include <utility>
2727
#include <vector>
2828

29-
fs::path GetConfigFile(const ArgsManager& args, const fs::path& configuration_file_path)
30-
{
31-
return AbsPathForConfigVal(args, configuration_file_path, /*net_specific=*/false);
32-
}
33-
3429
static bool GetConfigOptions(std::istream& stream, const std::string& filepath, std::string& error, std::vector<std::pair<std::string, std::string>>& options, std::list<SectionInfo>& sections)
3530
{
3631
std::string str, prefix;
@@ -125,6 +120,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
125120
LOCK(cs_args);
126121
m_settings.ro_config.clear();
127122
m_config_sections.clear();
123+
m_config_path = AbsPathForConfigVal(*this, GetPathArg("-conf", BITCOIN_CONF_FILENAME), /*net_specific=*/false);
128124
}
129125

130126
const auto conf_path{GetConfigFilePath()};
@@ -175,7 +171,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
175171
const size_t default_includes = add_includes({});
176172

177173
for (const std::string& conf_file_name : conf_file_names) {
178-
std::ifstream conf_file_stream{GetConfigFile(*this, fs::PathFromString(conf_file_name))};
174+
std::ifstream conf_file_stream{AbsPathForConfigVal(*this, fs::PathFromString(conf_file_name), /*net_specific=*/false)};
179175
if (conf_file_stream.good()) {
180176
if (!ReadConfigStream(conf_file_stream, conf_file_name, error, ignore_invalid_keys)) {
181177
return false;

src/common/init.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ std::optional<ConfigError> InitConfig(ArgsManager& args, SettingsAbortFn setting
3232
// parse error, and specifying a datadir= location containing another
3333
// bitcoin.conf file just ignores the other file.)
3434
const fs::path orig_datadir_path{args.GetDataDirBase()};
35-
const fs::path orig_config_path = args.GetConfigFilePath();
35+
const fs::path orig_config_path{AbsPathForConfigVal(args, args.GetPathArg("-conf", BITCOIN_CONF_FILENAME), /*net_specific=*/false)};
3636

3737
std::string error;
3838
if (!args.ReadConfigFiles(error, true)) {

src/qt/test/test_main.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ int main(int argc, char* argv[])
7070
gArgs.ForceSetArg("-upnp", "0");
7171
gArgs.ForceSetArg("-natpmp", "0");
7272

73+
std::string error;
74+
if (!gArgs.ReadConfigFiles(error, true)) QWARN(error.c_str());
75+
7376
// Prefer the "minimal" platform for the test instead of the normal default
7477
// platform ("xcb", "windows", or "cocoa") so tests can't unintentionally
7578
// interfere with any background GUIs and don't require extra resources.

test/functional/feature_config_args.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,41 @@ def test_config_file_parser(self):
113113
with open(inc_conf_file2_path, 'w', encoding='utf-8') as conf:
114114
conf.write('') # clear
115115

116+
def test_config_file_log(self):
117+
# Disable this test for windows currently because trying to override
118+
# the default datadir through the environment does not seem to work.
119+
if sys.platform == "win32":
120+
return
121+
122+
self.log.info('Test that correct configuration path is changed when configuration file changes the datadir')
123+
124+
# Create a temporary directory that will be treated as the default data
125+
# directory by bitcoind.
126+
env, default_datadir = util.get_temp_default_datadir(pathlib.Path(self.options.tmpdir, "test_config_file_log"))
127+
default_datadir.mkdir(parents=True)
128+
129+
# Write a bitcoin.conf file in the default data directory containing a
130+
# datadir= line pointing at the node datadir.
131+
node = self.nodes[0]
132+
conf_text = pathlib.Path(node.bitcoinconf).read_text()
133+
conf_path = default_datadir / "bitcoin.conf"
134+
conf_path.write_text(f"datadir={node.datadir}\n{conf_text}")
135+
136+
# Drop the node -datadir= argument during this test, because if it is
137+
# specified it would take precedence over the datadir setting in the
138+
# config file.
139+
node_args = node.args
140+
node.args = [arg for arg in node.args if not arg.startswith("-datadir=")]
141+
142+
# Check that correct configuration file path is actually logged
143+
# (conf_path, not node.bitcoinconf)
144+
with self.nodes[0].assert_debug_log(expected_msgs=[f"Config file: {conf_path}"]):
145+
self.start_node(0, ["-allowignoredconf"], env=env)
146+
self.stop_node(0)
147+
148+
# Restore node arguments after the test
149+
node.args = node_args
150+
116151
def test_invalid_command_line_options(self):
117152
self.nodes[0].assert_start_raises_init_error(
118153
expected_msg='Error: Error parsing command line arguments: Can not set -proxy with no value. Please specify value with -proxy=value.',
@@ -344,6 +379,7 @@ def run_test(self):
344379
self.test_connect_with_seednode()
345380

346381
self.test_config_file_parser()
382+
self.test_config_file_log()
347383
self.test_invalid_command_line_options()
348384
self.test_ignored_conf()
349385
self.test_ignored_default_conf()

0 commit comments

Comments
 (0)