diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 790d9033b08dd..d780d9f2254af 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -669,6 +669,7 @@ BOOST_AUTO_TEST_CASE(test_LockDirectory) BOOST_CHECK_EQUAL(processstatus, (int)false); #endif // Clean up + ReleaseDirectoryLocks(); fs::remove_all(dirname); } diff --git a/src/util.cpp b/src/util.cpp index 49f40dc942296..dcf7ed38b1195 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -373,19 +373,22 @@ int LogPrintStr(const std::string &str) return ret; } +/** A map that contains all the currently held directory locks. After + * successful locking, these will be held here until the global destructor + * cleans them up and thus automatically unlocks them, or ReleaseDirectoryLocks + * is called. + */ +static std::map> dir_locks; +/** Mutex to protect dir_locks. */ +static std::mutex cs_dir_locks; + bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only) { - // A map that contains all the currently held directory locks. After - // successful locking, these will be held here until the global - // destructor cleans them up and thus automatically unlocks them. - static std::map> locks; - // Protect the map with a mutex - static std::mutex cs; - std::lock_guard ulock(cs); + std::lock_guard ulock(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 (locks.count(pathLockFile.string())) { + if (dir_locks.count(pathLockFile.string())) { return true; } @@ -400,7 +403,7 @@ bool LockDirectory(const fs::path& directory, const std::string lockfile_name, b } if (!probe_only) { // Lock successful and we're not just probing, put it into the map - locks.emplace(pathLockFile.string(), std::move(lock)); + dir_locks.emplace(pathLockFile.string(), std::move(lock)); } } catch (const boost::interprocess::interprocess_exception& e) { return error("Error while attempting to lock directory %s: %s", directory.string(), e.what()); @@ -408,6 +411,12 @@ bool LockDirectory(const fs::path& directory, const std::string lockfile_name, b return true; } +void ReleaseDirectoryLocks() +{ + std::lock_guard ulock(cs_dir_locks); + dir_locks.clear(); +} + /** Interpret string as boolean, for argument parsing */ static bool InterpretBool(const std::string& strValue) { diff --git a/src/util.h b/src/util.h index 05138a9bfed95..9490a5678f2a8 100644 --- a/src/util.h +++ b/src/util.h @@ -174,6 +174,12 @@ int RaiseFileDescriptorLimit(int nMinFD); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); bool RenameOver(fs::path src, fs::path dest); bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only=false); + +/** Release all directory locks. This is used for unit testing only, at runtime + * the global destructor will take care of the locks. + */ +void ReleaseDirectoryLocks(); + bool TryCreateDirectories(const fs::path& p); fs::path GetDefaultDataDir(); const fs::path &GetDataDir(bool fNetSpecific = true);