aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2018-10-24 16:41:18 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2018-10-24 16:44:43 +0200
commita74ed3a05b27886e0a674c328e7ae13da8cacadb (patch)
tree10e24cc89360cf83b69f4c490f026d7ddc6f3636
parent9886590116b19b14b8dad38f70ff9df5af99064f (diff)
parent8907df9e02ec47ef249a7422faa766f06aa01e94 (diff)
Merge #14453: rpc: Fix wallet unload during walletpassphrase timeout
8907df9e02ec47ef249a7422faa766f06aa01e94 qa: Ensure wallet unload during walletpassphrase timeout (João Barbosa) 321decffa1fbf213462d97e5372bd0c4eeb99635 rpc: Fix wallet unload during walletpassphrase timeout (João Barbosa) Pull request description: Replaces the raw wallet pointer in the `RPCRunLater` callback with a `std::weak_ptr` to check if the wallet is not expired. To test: ``` bitcoind -regtest bitcoin-cli -regtest encryptwallet foobar bitcoin-cli -regtest walletpassphrase foobar 5 && bitcoin-cli -regtest unloadwallet "" ``` Fixes #14452. Tree-SHA512: 311e839234f5fb7955ab5412a2cfc1903ee7132ea56a8ab992ede3614586834886bd65192b76531ae0aa3a526b38e70ca2e1cdbabe52995906ff97b49d93c268
-rw-r--r--src/wallet/rpcwallet.cpp20
-rwxr-xr-xtest/functional/wallet_multiwallet.py5
2 files changed, 17 insertions, 8 deletions
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 5b97ad3ca1..dc39ba3001 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -1803,13 +1803,6 @@ static UniValue keypoolrefill(const JSONRPCRequest& request)
}
-static void LockWallet(CWallet* pWallet)
-{
- LOCK(pWallet->cs_wallet);
- pWallet->nRelockTime = 0;
- pWallet->Lock();
-}
-
static UniValue walletpassphrase(const JSONRPCRequest& request)
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
@@ -1879,7 +1872,18 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
pwallet->TopUpKeyPool();
pwallet->nRelockTime = GetTime() + nSleepTime;
- RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), std::bind(LockWallet, pwallet), nSleepTime);
+
+ // Keep a weak pointer to the wallet so that it is possible to unload the
+ // wallet before the following callback is called. If a valid shared pointer
+ // is acquired in the callback then the wallet is still loaded.
+ std::weak_ptr<CWallet> weak_wallet = wallet;
+ RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet] {
+ if (auto shared_wallet = weak_wallet.lock()) {
+ LOCK(shared_wallet->cs_wallet);
+ shared_wallet->Lock();
+ shared_wallet->nRelockTime = 0;
+ }
+ }, nSleepTime);
return NullUniValue;
}
diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
index 30ab750fac..c9108ae797 100755
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -8,6 +8,7 @@ Verify that a bitcoind node can load multiple wallet files
"""
import os
import shutil
+import time
from test_framework.test_framework import BitcoinTestFramework
from test_framework.test_node import ErrorMatch
@@ -273,7 +274,11 @@ class MultiWalletTest(BitcoinTestFramework):
assert 'w1' not in self.nodes[0].listwallets()
# Successfully unload the wallet referenced by the request endpoint
+ # Also ensure unload works during walletpassphrase timeout
+ w2.encryptwallet('test')
+ w2.walletpassphrase('test', 1)
w2.unloadwallet()
+ time.sleep(1.1)
assert 'w2' not in self.nodes[0].listwallets()
# Successfully unload all wallets