diff options
-rw-r--r-- | build_msvc/bitcoin_config.h.in | 3 | ||||
-rw-r--r-- | build_msvc/vcpkg.json | 1 | ||||
-rwxr-xr-x | ci/test/00_setup_env_win64.sh | 2 | ||||
-rw-r--r-- | configure.ac | 16 | ||||
-rw-r--r-- | depends/packages/capnp.mk | 11 | ||||
-rw-r--r-- | depends/packages/libmultiprocess.mk | 6 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/init.cpp | 11 | ||||
-rw-r--r-- | src/test/fs_tests.cpp | 24 | ||||
-rw-r--r-- | src/test/util_tests.cpp | 76 | ||||
-rw-r--r-- | src/util/fs_helpers.cpp | 34 | ||||
-rw-r--r-- | src/util/fs_helpers.h | 10 | ||||
-rw-r--r-- | src/util/getuniquepath.cpp | 14 | ||||
-rw-r--r-- | src/util/getuniquepath.h | 19 | ||||
-rw-r--r-- | src/wallet/bdb.cpp | 2 | ||||
-rwxr-xr-x | test/functional/test_runner.py | 3 |
16 files changed, 96 insertions, 139 deletions
diff --git a/build_msvc/bitcoin_config.h.in b/build_msvc/bitcoin_config.h.in index 1716647486..ec69307f50 100644 --- a/build_msvc/bitcoin_config.h.in +++ b/build_msvc/bitcoin_config.h.in @@ -41,9 +41,6 @@ /* Define this symbol to enable ZMQ functions */ #define ENABLE_ZMQ 1 -/* define if external signer support is enabled (requires Boost::Process) */ -#define ENABLE_EXTERNAL_SIGNER /**/ - /* Define to 1 if you have the declaration of `be16toh', and to 0 if you don't. */ #define HAVE_DECL_BE16TOH 0 diff --git a/build_msvc/vcpkg.json b/build_msvc/vcpkg.json index 18ac8f2f09..b2c406ae12 100644 --- a/build_msvc/vcpkg.json +++ b/build_msvc/vcpkg.json @@ -5,7 +5,6 @@ "berkeleydb", "boost-date-time", "boost-multi-index", - "boost-process", "boost-signals2", "boost-test", "libevent", diff --git a/ci/test/00_setup_env_win64.sh b/ci/test/00_setup_env_win64.sh index ebd4487c52..ba9af480ac 100755 --- a/ci/test/00_setup_env_win64.sh +++ b/ci/test/00_setup_env_win64.sh @@ -16,4 +16,4 @@ export GOAL="deploy" # Prior to 11.0.0, the mingw-w64 headers were missing noreturn attributes, causing warnings when # cross-compiling for Windows. https://sourceforge.net/p/mingw-w64/bugs/306/ # https://github.com/mingw-w64/mingw-w64/commit/1690994f515910a31b9fb7c7bd3a52d4ba987abe -export BITCOIN_CONFIG="--enable-reduce-exports --enable-external-signer --disable-gui-tests CXXFLAGS=-Wno-return-type" +export BITCOIN_CONFIG="--enable-reduce-exports --disable-gui-tests CXXFLAGS=-Wno-return-type" diff --git a/configure.ac b/configure.ac index dcf4f10426..7b286df603 100644 --- a/configure.ac +++ b/configure.ac @@ -1505,9 +1505,19 @@ if test "$use_external_signer" != "no"; then CXXFLAGS="$TEMP_CXXFLAGS" AC_MSG_RESULT([$have_boost_process]) if test "$have_boost_process" = "yes"; then - use_external_signer="yes" - AC_DEFINE([ENABLE_EXTERNAL_SIGNER], [1], [Define if external signer support is enabled]) - AC_DEFINE([BOOST_PROCESS_USE_STD_FS], [1], [Defined to avoid Boost::Process trying to use Boost Filesystem]) + case $host in + dnl Boost Process for Windows uses Boost ASIO. Boost ASIO performs + dnl pre-main init of Windows networking libraries, which we do not + dnl want. + *mingw*) + use_external_signer="no" + ;; + *) + use_external_signer="yes" + AC_DEFINE([ENABLE_EXTERNAL_SIGNER], [1], [Define if external signer support is enabled]) + AC_DEFINE([BOOST_PROCESS_USE_STD_FS], [1], [Defined to avoid Boost::Process trying to use Boost Filesystem]) + ;; + esac else if test "$use_external_signer" = "yes"; then AC_MSG_ERROR([External signing is not supported for this Boost version]) diff --git a/depends/packages/capnp.mk b/depends/packages/capnp.mk index 1c1a77eb16..2465c8091b 100644 --- a/depends/packages/capnp.mk +++ b/depends/packages/capnp.mk @@ -5,10 +5,15 @@ $(package)_download_file=$(native_$(package)_download_file) $(package)_file_name=$(native_$(package)_file_name) $(package)_sha256_hash=$(native_$(package)_sha256_hash) +# Hardcode library install path to "lib" to match the PKG_CONFIG_PATH +# setting in depends/config.site.in, which also hardcodes "lib". +# Without this setting, cmake by default would use the OS library +# directory, which might be "lib64" or something else, not "lib", on multiarch systems. define $(package)_set_vars := -$(package)_config_opts := -DBUILD_TESTING=OFF -$(package)_config_opts += -DWITH_OPENSSL=OFF -$(package)_config_opts += -DWITH_ZLIB=OFF + $(package)_config_opts := -DBUILD_TESTING=OFF + $(package)_config_opts += -DWITH_OPENSSL=OFF + $(package)_config_opts += -DWITH_ZLIB=OFF + $(package)_config_opts += -DCMAKE_INSTALL_LIBDIR=lib/ endef define $(package)_config_cmds diff --git a/depends/packages/libmultiprocess.mk b/depends/packages/libmultiprocess.mk index 765d649377..d237f52dbb 100644 --- a/depends/packages/libmultiprocess.mk +++ b/depends/packages/libmultiprocess.mk @@ -8,7 +8,13 @@ ifneq ($(host),$(build)) $(package)_dependencies += native_capnp endif +# Hardcode library install path to "lib" to match the PKG_CONFIG_PATH +# setting in depends/config.site.in, which also hardcodes "lib". +# Without this setting, cmake by default would use the OS library +# directory, which might be "lib64" or something else, not "lib", on multiarch systems. define $(package)_set_vars := +$(package)_config_opts += -DCMAKE_INSTALL_LIBDIR=lib/ +$(package)_config_opts += -DCMAKE_POSITION_INDEPENDENT_CODE=ON ifneq ($(host),$(build)) $(package)_config_opts := -DCAPNP_EXECUTABLE="$$(native_capnp_prefixbin)/capnp" $(package)_config_opts += -DCAPNPC_CXX_EXECUTABLE="$$(native_capnp_prefixbin)/capnpc-c++" diff --git a/src/Makefile.am b/src/Makefile.am index df56ac7090..d25b27dd3e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -304,7 +304,6 @@ BITCOIN_CORE_H = \ util/fees.h \ util/fs.h \ util/fs_helpers.h \ - util/getuniquepath.h \ util/golombrice.h \ util/hash_type.h \ util/hasher.h \ @@ -741,7 +740,6 @@ libbitcoin_util_a_SOURCES = \ util/fees.cpp \ util/fs.cpp \ util/fs_helpers.cpp \ - util/getuniquepath.cpp \ util/hasher.cpp \ util/sock.cpp \ util/syserror.cpp \ @@ -984,7 +982,6 @@ libbitcoinkernel_la_SOURCES = \ util/exception.cpp \ util/fs.cpp \ util/fs_helpers.cpp \ - util/getuniquepath.cpp \ util/hasher.cpp \ util/moneystr.cpp \ util/rbf.cpp \ diff --git a/src/init.cpp b/src/init.cpp index ac52b34fc5..d1a0ca1c3b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1047,13 +1047,14 @@ static bool LockDataDirectory(bool probeOnly) { // Make sure only a single Bitcoin process is using the data directory. const fs::path& datadir = gArgs.GetDataDirNet(); - if (!DirIsWritable(datadir)) { + switch (util::LockDirectory(datadir, ".lock", probeOnly)) { + case util::LockResult::ErrorWrite: return InitError(strprintf(_("Cannot write to data directory '%s'; check permissions."), fs::PathToString(datadir))); - } - if (!LockDirectory(datadir, ".lock", probeOnly)) { + case util::LockResult::ErrorLock: return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), fs::PathToString(datadir), PACKAGE_NAME)); - } - return true; + case util::LockResult::Success: return true; + } // no default case, so the compiler can warn about missing cases + assert(false); } bool AppInitSanityChecks(const kernel::Context& kernel) diff --git a/src/test/fs_tests.cpp b/src/test/fs_tests.cpp index 7cfecb2b22..0d25428b33 100644 --- a/src/test/fs_tests.cpp +++ b/src/test/fs_tests.cpp @@ -5,7 +5,6 @@ #include <test/util/setup_common.h> #include <util/fs.h> #include <util/fs_helpers.h> -#include <util/getuniquepath.h> #include <boost/test/unit_test.hpp> @@ -101,29 +100,14 @@ BOOST_AUTO_TEST_CASE(fsbridge_fstream) BOOST_CHECK_EQUAL(tmpfile1, fsbridge::AbsPathJoin(tmpfile1, "")); BOOST_CHECK_EQUAL(tmpfile1, fsbridge::AbsPathJoin(tmpfile1, {})); } - { - fs::path p1 = GetUniquePath(tmpfolder); - fs::path p2 = GetUniquePath(tmpfolder); - fs::path p3 = GetUniquePath(tmpfolder); - - // Ensure that the parent path is always the same. - BOOST_CHECK_EQUAL(tmpfolder, p1.parent_path()); - BOOST_CHECK_EQUAL(tmpfolder, p2.parent_path()); - BOOST_CHECK_EQUAL(tmpfolder, p3.parent_path()); - - // Ensure that generated paths are actually different. - BOOST_CHECK(p1 != p2); - BOOST_CHECK(p2 != p3); - BOOST_CHECK(p1 != p3); - } } BOOST_AUTO_TEST_CASE(rename) { const fs::path tmpfolder{m_args.GetDataDirBase()}; - const fs::path path1{GetUniquePath(tmpfolder)}; - const fs::path path2{GetUniquePath(tmpfolder)}; + const fs::path path1{tmpfolder / "a"}; + const fs::path path2{tmpfolder / "b"}; const std::string path1_contents{"1111"}; const std::string path2_contents{"2222"}; @@ -158,13 +142,13 @@ BOOST_AUTO_TEST_CASE(create_directories) // Test fs::create_directories workaround. const fs::path tmpfolder{m_args.GetDataDirBase()}; - const fs::path dir{GetUniquePath(tmpfolder)}; + const fs::path dir{tmpfolder / "a"}; fs::create_directory(dir); BOOST_CHECK(fs::exists(dir)); BOOST_CHECK(fs::is_directory(dir)); BOOST_CHECK(!fs::create_directories(dir)); - const fs::path symlink{GetUniquePath(tmpfolder)}; + const fs::path symlink{tmpfolder / "b"}; fs::create_directory_symlink(dir, symlink); BOOST_CHECK(fs::exists(symlink)); BOOST_CHECK(fs::is_symlink(symlink)); diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 4d812544bd..47808a2a58 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -12,7 +12,6 @@ #include <util/bitdeque.h> #include <util/fs.h> #include <util/fs_helpers.h> -#include <util/getuniquepath.h> #include <util/message.h> // For MessageSign(), MessageVerify(), MESSAGE_MAGIC #include <util/moneystr.h> #include <util/overflow.h> @@ -1106,15 +1105,16 @@ BOOST_AUTO_TEST_CASE(test_ParseFixedPoint) BOOST_CHECK(!ParseFixedPoint("31.999999999999999999999", 3, &amount)); } -static void TestOtherThread(fs::path dirname, fs::path lockname, bool *result) -{ - *result = LockDirectory(dirname, lockname); -} - #ifndef WIN32 // Cannot do this test on WIN32 due to lack of fork() static constexpr char LockCommand = 'L'; static constexpr char UnlockCommand = 'U'; static constexpr char ExitCommand = 'X'; +enum : char { + ResSuccess = 2, // Start with 2 to avoid accidental collision with common values 0 and 1 + ResErrorWrite, + ResErrorLock, + ResUnlockSuccess, +}; [[noreturn]] static void TestOtherProcess(fs::path dirname, fs::path lockname, int fd) { @@ -1122,15 +1122,22 @@ static constexpr char ExitCommand = 'X'; while (true) { int rv = read(fd, &ch, 1); // Wait for command assert(rv == 1); - switch(ch) { + switch (ch) { case LockCommand: - ch = LockDirectory(dirname, lockname); + ch = [&] { + switch (util::LockDirectory(dirname, lockname)) { + case util::LockResult::Success: return ResSuccess; + case util::LockResult::ErrorWrite: return ResErrorWrite; + case util::LockResult::ErrorLock: return ResErrorLock; + } // no default case, so the compiler can warn about missing cases + assert(false); + }(); rv = write(fd, &ch, 1); assert(rv == 1); break; case UnlockCommand: ReleaseDirectoryLocks(); - ch = true; // Always succeeds + ch = ResUnlockSuccess; // Always succeeds rv = write(fd, &ch, 1); assert(rv == 1); break; @@ -1165,53 +1172,58 @@ BOOST_AUTO_TEST_CASE(test_LockDirectory) TestOtherProcess(dirname, lockname, fd[0]); } BOOST_CHECK_EQUAL(close(fd[0]), 0); // Parent: close child end + + char ch; + // Lock on non-existent directory should fail + BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1); + BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1); + BOOST_CHECK_EQUAL(ch, ResErrorWrite); #endif // Lock on non-existent directory should fail - BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), false); + BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname), util::LockResult::ErrorWrite); fs::create_directories(dirname); // Probing lock on new directory should succeed - BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true); + BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success); // Persistent lock on new directory should succeed - BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), true); + BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname), util::LockResult::Success); // Another lock on the directory from the same thread should succeed - BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), true); + BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname), util::LockResult::Success); // Another lock on the directory from a different thread within the same process should succeed - bool threadresult; - std::thread thr(TestOtherThread, dirname, lockname, &threadresult); + util::LockResult threadresult; + std::thread thr([&] { threadresult = util::LockDirectory(dirname, lockname); }); thr.join(); - BOOST_CHECK_EQUAL(threadresult, true); + BOOST_CHECK_EQUAL(threadresult, util::LockResult::Success); #ifndef WIN32 // Try to acquire lock in child process while we're holding it, this should fail. - char ch; BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1); BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1); - BOOST_CHECK_EQUAL((bool)ch, false); + BOOST_CHECK_EQUAL(ch, ResErrorLock); // Give up our lock ReleaseDirectoryLocks(); // Probing lock from our side now should succeed, but not hold on to the lock. - BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true); + BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success); // Try to acquire the lock in the child process, this should be successful. BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1); BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1); - BOOST_CHECK_EQUAL((bool)ch, true); + BOOST_CHECK_EQUAL(ch, ResSuccess); // When we try to probe the lock now, it should fail. - BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), false); + BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::ErrorLock); // Unlock the lock in the child process BOOST_CHECK_EQUAL(write(fd[1], &UnlockCommand, 1), 1); BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1); - BOOST_CHECK_EQUAL((bool)ch, true); + BOOST_CHECK_EQUAL(ch, ResUnlockSuccess); // When we try to probe the lock now, it should succeed. - BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true); + BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success); // Re-lock the lock in the child process, then wait for it to exit, check // successful return. After that, we check that exiting the process @@ -1224,7 +1236,7 @@ BOOST_AUTO_TEST_CASE(test_LockDirectory) BOOST_CHECK_EQUAL(write(fd[1], &ExitCommand, 1), 1); BOOST_CHECK_EQUAL(waitpid(pid, &processstatus, 0), pid); BOOST_CHECK_EQUAL(processstatus, 0); - BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true); + BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success); // Restore SIGCHLD signal(SIGCHLD, old_handler); @@ -1235,22 +1247,6 @@ BOOST_AUTO_TEST_CASE(test_LockDirectory) fs::remove_all(dirname); } -BOOST_AUTO_TEST_CASE(test_DirIsWritable) -{ - // Should be able to write to the data dir. - fs::path tmpdirname = m_args.GetDataDirBase(); - BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true); - - // Should not be able to write to a non-existent dir. - tmpdirname = GetUniquePath(tmpdirname); - BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), false); - - fs::create_directory(tmpdirname); - // Should be able to write to it now. - BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true); - fs::remove(tmpdirname); -} - BOOST_AUTO_TEST_CASE(test_ToLower) { BOOST_CHECK_EQUAL(ToLower('@'), '@'); diff --git a/src/util/fs_helpers.cpp b/src/util/fs_helpers.cpp index 8aa7493aa8..4de8833a3f 100644 --- a/src/util/fs_helpers.cpp +++ b/src/util/fs_helpers.cpp @@ -12,7 +12,6 @@ #include <logging.h> #include <sync.h> #include <util/fs.h> -#include <util/getuniquepath.h> #include <util/syserror.h> #include <cerrno> @@ -51,31 +50,35 @@ static GlobalMutex cs_dir_locks; * is called. */ static std::map<std::string, std::unique_ptr<fsbridge::FileLock>> dir_locks GUARDED_BY(cs_dir_locks); - -bool LockDirectory(const fs::path& directory, const fs::path& lockfile_name, bool probe_only) +namespace util { +LockResult LockDirectory(const fs::path& directory, const fs::path& lockfile_name, bool probe_only) { LOCK(cs_dir_locks); fs::path pathLockFile = directory / lockfile_name; // If a lock for this directory already exists in the map, don't try to re-lock it if (dir_locks.count(fs::PathToString(pathLockFile))) { - return true; + return LockResult::Success; } // Create empty lock file if it doesn't exist. - FILE* file = fsbridge::fopen(pathLockFile, "a"); - if (file) fclose(file); + if (auto created{fsbridge::fopen(pathLockFile, "a")}) { + std::fclose(created); + } else { + return LockResult::ErrorWrite; + } auto lock = std::make_unique<fsbridge::FileLock>(pathLockFile); if (!lock->TryLock()) { - return error("Error while attempting to lock directory %s: %s", fs::PathToString(directory), lock->GetReason()); + error("Error while attempting to lock directory %s: %s", fs::PathToString(directory), lock->GetReason()); + return LockResult::ErrorLock; } if (!probe_only) { // Lock successful and we're not just probing, put it into the map dir_locks.emplace(fs::PathToString(pathLockFile), std::move(lock)); } - return true; + return LockResult::Success; } - +} // namespace util void UnlockDirectory(const fs::path& directory, const fs::path& lockfile_name) { LOCK(cs_dir_locks); @@ -88,19 +91,6 @@ void ReleaseDirectoryLocks() dir_locks.clear(); } -bool DirIsWritable(const fs::path& directory) -{ - fs::path tmpFile = GetUniquePath(directory); - - FILE* file = fsbridge::fopen(tmpFile, "a"); - if (!file) return false; - - fclose(file); - remove(tmpFile); - - return true; -} - bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes) { constexpr uint64_t min_disk_space = 52428800; // 50 MiB diff --git a/src/util/fs_helpers.h b/src/util/fs_helpers.h index e7db01a89b..ea3778eac3 100644 --- a/src/util/fs_helpers.h +++ b/src/util/fs_helpers.h @@ -35,9 +35,15 @@ void AllocateFileRange(FILE* file, unsigned int offset, unsigned int length); */ [[nodiscard]] bool RenameOver(fs::path src, fs::path dest); -bool LockDirectory(const fs::path& directory, const fs::path& lockfile_name, bool probe_only = false); +namespace util { +enum class LockResult { + Success, + ErrorWrite, + ErrorLock, +}; +[[nodiscard]] LockResult LockDirectory(const fs::path& directory, const fs::path& lockfile_name, bool probe_only = false); +} // namespace util void UnlockDirectory(const fs::path& directory, const fs::path& lockfile_name); -bool DirIsWritable(const fs::path& directory); bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes = 0); /** Get the size of a file by scanning it. diff --git a/src/util/getuniquepath.cpp b/src/util/getuniquepath.cpp deleted file mode 100644 index 105b4d52d2..0000000000 --- a/src/util/getuniquepath.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) 2021-2022 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 <random.h> -#include <util/fs.h> -#include <util/strencodings.h> - -fs::path GetUniquePath(const fs::path& base) -{ - FastRandomContext rnd; - fs::path tmpFile = base / fs::u8path(HexStr(rnd.randbytes(8))); - return tmpFile; -}
\ No newline at end of file diff --git a/src/util/getuniquepath.h b/src/util/getuniquepath.h deleted file mode 100644 index 1563652300..0000000000 --- a/src/util/getuniquepath.h +++ /dev/null @@ -1,19 +0,0 @@ -// 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. - -#ifndef BITCOIN_UTIL_GETUNIQUEPATH_H -#define BITCOIN_UTIL_GETUNIQUEPATH_H - -#include <util/fs.h> - -/** - * Helper function for getting a unique path - * - * @param[in] base Base path - * @returns base joined with a random 8-character long string. - * @post Returned path is unique with high probability. - */ -fs::path GetUniquePath(const fs::path& base); - -#endif // BITCOIN_UTIL_GETUNIQUEPATH_H
\ No newline at end of file diff --git a/src/wallet/bdb.cpp b/src/wallet/bdb.cpp index 9ea43ca67c..cbf6c9b1ea 100644 --- a/src/wallet/bdb.cpp +++ b/src/wallet/bdb.cpp @@ -149,7 +149,7 @@ bool BerkeleyEnvironment::Open(bilingual_str& err) fs::path pathIn = fs::PathFromString(strPath); TryCreateDirectories(pathIn); - if (!LockDirectory(pathIn, ".walletlock")) { + if (util::LockDirectory(pathIn, ".walletlock") != util::LockResult::Success) { LogPrintf("Cannot obtain a lock on wallet directory %s. Another instance may be using it.\n", strPath); err = strprintf(_("Error initializing wallet database environment %s!"), fs::quoted(fs::PathToString(Directory()))); return false; diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 6016a482f8..bf52ba6d93 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -565,8 +565,7 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage= test_framework_tests.addTest(unittest.TestLoader().loadTestsFromName("test_framework.{}".format(module))) result = unittest.TextTestRunner(verbosity=1, failfast=True).run(test_framework_tests) if not result.wasSuccessful(): - logging.debug("Early exiting after failure in TestFramework unit tests") - sys.exit(False) + sys.exit("Early exiting after failure in TestFramework unit tests") flags = ['--cachedir={}'.format(cache_dir)] + args |