mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-14 08:39:35 +02:00
Merge #14941: rpc: Make unloadwallet wait for complete wallet unload
645e905c32doc: Add release notes for unloadwallet change to synchronous call (João Barbosa)c37851de57rpc: Make unloadwallet wait for complete wallet unload (João Barbosa) Pull request description: Currently the `unloadwallet` RPC is asynchronous, it only signals the intent to unload the wallet and then returns the response to the client. The actual unload can happen later and the client has no way to be notified of that. This PR makes the `unloadwallet` RPC synchronous, meaning that it blocks until the wallet is fully unloaded. Replaces #14919, fixes #14917. Tree-SHA512: ad88b980e2f3652809a58f904afbfe020299f3aa6a517f495ba943b8d54d4520f6e70074d6749be8f5967065c0f476e0faedcde64c8b4899e5f99c70f0fd6534
This commit is contained in:
@@ -82,13 +82,52 @@ std::shared_ptr<CWallet> GetWallet(const std::string& name)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static 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.
|
||||
{
|
||||
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();
|
||||
{
|
||||
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();
|
||||
{
|
||||
WAIT_LOCK(g_wallet_release_mutex, lock);
|
||||
while (g_unloading_wallet_set.count(pwallet) == 1) {
|
||||
g_wallet_release_cv.wait(lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
|
||||
|
||||
Reference in New Issue
Block a user