Skip to content

Commit 41106a5

Browse files
committed
qt: get required locks upfront in polling functions
This avoids the GUI from getting stuck on periodical polls if the core is holding the locks for a longer time - for example, during a wallet rescan.
1 parent ed67100 commit 41106a5

File tree

3 files changed

+34
-18
lines changed

3 files changed

+34
-18
lines changed

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();

0 commit comments

Comments
 (0)