Skip to content

Commit 89bbd54

Browse files
committed
Merge pull request #4085
b39a07d Add missing AssertLockHeld in ConnectBlock (Wladimir J. van der Laan) 41106a5 qt: get required locks upfront in polling functions (Wladimir J. van der Laan) ed67100 Add required locks in tests (Wladimir J. van der Laan)
2 parents 97730c9 + b39a07d commit 89bbd54

File tree

7 files changed

+40
-19
lines changed

7 files changed

+40
-19
lines changed

src/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,6 +1727,7 @@ void ThreadScriptCheck() {
17271727

17281728
bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck)
17291729
{
1730+
AssertLockHeld(cs_main);
17301731
// Check it again in case a previous version let a bad block in
17311732
if (!CheckBlock(block, state, !fJustCheck, !fJustCheck))
17321733
return false;

src/qt/clientmodel.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ double ClientModel::getVerificationProgress() const
9292

9393
void ClientModel::updateTimer()
9494
{
95+
// Get required lock upfront. This avoids the GUI from getting stuck on
96+
// periodical polls if the core is holding the locks for a longer time -
97+
// for example, during a wallet rescan.
98+
TRY_LOCK(cs_main, lockMain);
99+
if(!lockMain)
100+
return;
95101
// Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change.
96102
// Periodically check and update with a timer.
97103
int newNumBlocks = getNumBlocks();

src/qt/transactiontablemodel.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
#include <QDebug>
2525
#include <QIcon>
2626
#include <QList>
27-
#include <QTimer>
2827

2928
// Amount column is right-aligned it contains numbers
3029
static int column_alignments[] = {
@@ -187,17 +186,25 @@ class TransactionTablePriv
187186
{
188187
TransactionRecord *rec = &cachedWallet[idx];
189188

189+
// Get required locks upfront. This avoids the GUI from getting
190+
// stuck if the core is holding the locks for a longer time - for
191+
// example, during a wallet rescan.
192+
//
190193
// If a status update is needed (blocks came in since last check),
191194
// update the status of this transaction from the wallet. Otherwise,
192195
// simply re-use the cached status.
193-
LOCK2(cs_main, wallet->cs_wallet);
194-
if(rec->statusUpdateNeeded())
196+
TRY_LOCK(cs_main, lockMain);
197+
if(lockMain)
195198
{
196-
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
197-
198-
if(mi != wallet->mapWallet.end())
199+
TRY_LOCK(wallet->cs_wallet, lockWallet);
200+
if(lockWallet && rec->statusUpdateNeeded())
199201
{
200-
rec->updateStatus(mi->second);
202+
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
203+
204+
if(mi != wallet->mapWallet.end())
205+
{
206+
rec->updateStatus(mi->second);
207+
}
201208
}
202209
}
203210
return rec;

src/qt/walletmodel.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -98,18 +98,21 @@ void WalletModel::updateStatus()
9898

9999
void WalletModel::pollBalanceChanged()
100100
{
101-
bool heightChanged = false;
102-
{
103-
LOCK(cs_main);
104-
if(chainActive.Height() != cachedNumBlocks)
105-
{
106-
// Balance and number of transactions might have changed
107-
cachedNumBlocks = chainActive.Height();
108-
heightChanged = true;
109-
}
110-
}
111-
if(heightChanged)
101+
// Get required locks upfront. This avoids the GUI from getting stuck on
102+
// periodical polls if the core is holding the locks for a longer time -
103+
// for example, during a wallet rescan.
104+
TRY_LOCK(cs_main, lockMain);
105+
if(!lockMain)
106+
return;
107+
TRY_LOCK(wallet->cs_wallet, lockWallet);
108+
if(!lockWallet)
109+
return;
110+
111+
if(chainActive.Height() != cachedNumBlocks)
112112
{
113+
// Balance and number of transactions might have changed
114+
cachedNumBlocks = chainActive.Height();
115+
113116
checkBalanceChanged();
114117
if(transactionTableModel)
115118
transactionTableModel->updateConfirmations();

src/test/rpc_wallet_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
6565
// Test RPC calls for various wallet statistics
6666
Value r;
6767

68-
LOCK(pwalletMain->cs_wallet);
68+
LOCK2(cs_main, pwalletMain->cs_wallet);
6969

7070
BOOST_CHECK_NO_THROW(CallRPC("listunspent"));
7171
BOOST_CHECK_THROW(CallRPC("listunspent string"), runtime_error);

src/test/script_P2SH_tests.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ BOOST_AUTO_TEST_SUITE(script_P2SH_tests)
5050

5151
BOOST_AUTO_TEST_CASE(sign)
5252
{
53+
LOCK(cs_main);
5354
// Pay-to-script-hash looks like this:
5455
// scriptSig: <sig> <sig...> <serialized_script>
5556
// scriptPubKey: HASH160 <hash> EQUAL
@@ -147,6 +148,7 @@ BOOST_AUTO_TEST_CASE(norecurse)
147148

148149
BOOST_AUTO_TEST_CASE(set)
149150
{
151+
LOCK(cs_main);
150152
// Test the CScript::Set* methods
151153
CBasicKeyStore keystore;
152154
CKey key[4];
@@ -250,6 +252,7 @@ BOOST_AUTO_TEST_CASE(switchover)
250252

251253
BOOST_AUTO_TEST_CASE(AreInputsStandard)
252254
{
255+
LOCK(cs_main);
253256
CCoinsView coinsDummy;
254257
CCoinsViewCache coins(coinsDummy);
255258
CBasicKeyStore keystore;

src/test/transaction_tests.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ BOOST_AUTO_TEST_CASE(test_Get)
254254

255255
BOOST_AUTO_TEST_CASE(test_IsStandard)
256256
{
257+
LOCK(cs_main);
257258
CBasicKeyStore keystore;
258259
CCoinsView coinsDummy;
259260
CCoinsViewCache coins(coinsDummy);

0 commit comments

Comments
 (0)