aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet.cpp
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2019-01-31 15:35:26 +0100
committerWladimir J. van der Laan <laanwj@gmail.com>2019-01-31 15:35:30 +0100
commit30db5cc6418aa104c05b21ceceea3f04d1066b5f (patch)
treecc1e5be832e20b396b0f15500f134cf531f186df /src/wallet/wallet.cpp
parent09a9238c045670ce22a2798a717925248d1483f4 (diff)
parent0cd9ad208c327127cc4616ccdc37557fad3cf381 (diff)
downloadbitcoin-30db5cc6418aa104c05b21ceceea3f04d1066b5f.tar.xz
Merge #15002: 0.17: Backport #14941
0cd9ad208c327127cc4616ccdc37557fad3cf381 rpc: Make unloadwallet wait for complete wallet unload (João Barbosa) Pull request description: #14941 makes `unloadwallet` a synchronous call meaning that it waits for the wallet to fully unload/delete. Tree-SHA512: df7a490306ee2cca399129a4ebfba4b19b65fe67d1657ec3518352fe453327cb347010f94cf7fe4a60aeb51c928cb9ad6b24c40123fd0b9dc0aab5920a59f48d
Diffstat (limited to 'src/wallet/wallet.cpp')
-rw-r--r--src/wallet/wallet.cpp39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 060325921f..e86aa04d18 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -81,13 +81,52 @@ std::shared_ptr<CWallet> GetWallet(const std::string& name)
return nullptr;
}
+static std::mutex g_wallet_release_mutex;
+static std::condition_variable g_wallet_release_cv;
+static std::set<CWallet*> g_unloading_wallet_set;
+
// Custom deleter for shared_ptr<CWallet>.
static void ReleaseWallet(CWallet* wallet)
{
+ // Unregister and delete the wallet right after BlockUntilSyncedToCurrentChain
+ // so that it's in sync with the current chainstate.
wallet->WalletLogPrintf("Releasing wallet\n");
wallet->BlockUntilSyncedToCurrentChain();
wallet->Flush();
+ UnregisterValidationInterface(wallet);
delete wallet;
+ // Wallet is now released, notify UnloadWallet, if any.
+ {
+ std::lock_guard<std::mutex> lock(g_wallet_release_mutex);
+ if (g_unloading_wallet_set.erase(wallet) == 0) {
+ // UnloadWallet was not called for this wallet, all done.
+ return;
+ }
+ }
+ g_wallet_release_cv.notify_all();
+}
+
+void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
+{
+ // Mark wallet for unloading.
+ CWallet* pwallet = wallet.get();
+ {
+ std::lock_guard<std::mutex> lock(g_wallet_release_mutex);
+ auto it = g_unloading_wallet_set.insert(pwallet);
+ assert(it.second);
+ }
+ // The wallet can be in use so it's not possible to explicitly unload here.
+ // Notify the unload intent so that all remaining shared pointers are
+ // released.
+ pwallet->NotifyUnload();
+ // Time to ditch our shared_ptr and wait for ReleaseWallet call.
+ wallet.reset();
+ {
+ std::unique_lock<std::mutex> lock(g_wallet_release_mutex);
+ while (g_unloading_wallet_set.count(pwallet) == 1) {
+ g_wallet_release_cv.wait(lock);
+ }
+ }
}
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;