From c9b49d28563487e76169c7749b309244cabc70bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Barbosa?= Date: Wed, 17 Jun 2020 10:47:29 +0100 Subject: wallet: Handle concurrent wallet loading Github-Pull: #19300 Rebased-From: b9971ae5853c1d62e09d976a8705f4f731290d85 --- src/wallet/wallet.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'src') 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 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 g_unloading_wallet_set; +static std::set g_loading_wallet_set GUARDED_BY(g_loading_wallet_mutex); +static std::set g_unloading_wallet_set GUARDED_BY(g_wallet_release_mutex); // Custom deleter for shared_ptr. static void ReleaseWallet(CWallet* wallet) @@ -147,7 +149,8 @@ void UnloadWallet(std::shared_ptr&& wallet) } } -std::shared_ptr LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector& warnings) +namespace { +std::shared_ptr LoadWalletInternal(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector& warnings) { try { if (!CWallet::Verify(chain, location, false, error, warnings)) { @@ -168,6 +171,19 @@ std::shared_ptr LoadWallet(interfaces::Chain& chain, const WalletLocati return nullptr; } } +} // namespace + +std::shared_ptr LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::vector& 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 LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::vector& warnings) { -- cgit v1.2.3