aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoão Barbosa <joao.paulo.barbosa@gmail.com>2020-06-17 10:47:29 +0100
committerfanquake <fanquake@gmail.com>2020-07-03 09:51:24 +0800
commitc9b49d28563487e76169c7749b309244cabc70bd (patch)
treea72f81f07246c6a70180a998fff090bee7ad10e4 /src
parentcf0b5a933da540416b530ca6eb0259ab18cc6548 (diff)
downloadbitcoin-c9b49d28563487e76169c7749b309244cabc70bd.tar.xz
wallet: Handle concurrent wallet loading
Github-Pull: #19300 Rebased-From: b9971ae5853c1d62e09d976a8705f4f731290d85
Diffstat (limited to 'src')
-rw-r--r--src/wallet/wallet.cpp20
1 files changed, 18 insertions, 2 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 4394b2748a..af3f958349 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -101,9 +101,11 @@ std::unique_ptr<interfaces::Handler> HandleLoadWallet(LoadWalletFn load_wallet)
return interfaces::MakeHandler([it] { LOCK(cs_wallets); g_load_wallet_fns.erase(it); });
}
+static Mutex g_loading_wallet_mutex;
static Mutex g_wallet_release_mutex;
static std::condition_variable g_wallet_release_cv;
-static std::set<std::string> g_unloading_wallet_set;
+static std::set<std::string> g_loading_wallet_set GUARDED_BY(g_loading_wallet_mutex);
+static std::set<std::string> g_unloading_wallet_set GUARDED_BY(g_wallet_release_mutex);
// Custom deleter for shared_ptr<CWallet>.
static void ReleaseWallet(CWallet* wallet)
@@ -147,7 +149,8 @@ void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
}
}
-std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings)
+namespace {
+std::shared_ptr<CWallet> LoadWalletInternal(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings)
{
try {
if (!CWallet::Verify(chain, location, false, error, warnings)) {
@@ -168,6 +171,19 @@ std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocati
return nullptr;
}
}
+} // namespace
+
+std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector<std::string>& warnings)
+{
+ auto result = WITH_LOCK(g_loading_wallet_mutex, return g_loading_wallet_set.insert(location.GetName()));
+ if (!result.second) {
+ error = "Wallet already being loading.";
+ return nullptr;
+ }
+ auto wallet = LoadWalletInternal(chain, location, error, warnings);
+ WITH_LOCK(g_loading_wallet_mutex, g_loading_wallet_set.erase(result.first));
+ return wallet;
+}
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::vector<std::string>& warnings)
{