Skip to content

Commit 9a1d73f

Browse files
committed
Fix segfault when shutdown during wallet open
If you open a wallet and send a shutdown signal during that process, the GUI will segfault due to some queued wallet events happening after the wallet controller is deleted. This is a minimal fix for those issues.
1 parent 65de8ee commit 9a1d73f

File tree

3 files changed

+17
-6
lines changed

3 files changed

+17
-6
lines changed

src/qt/bitcoingui.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,10 @@ void BitcoinGUI::setWalletController(WalletController* wallet_controller)
680680

681681
GUIUtil::ExceptionSafeConnect(wallet_controller, &WalletController::walletAdded, this, &BitcoinGUI::addWallet);
682682
connect(wallet_controller, &WalletController::walletRemoved, this, &BitcoinGUI::removeWallet);
683+
connect(wallet_controller, &WalletController::destroyed, this, [this] {
684+
// wallet_controller gets destroyed manually, but it leaves our member copy dangling
685+
m_wallet_controller = nullptr;
686+
});
683687

684688
auto activity = new LoadWalletsActivity(m_wallet_controller, this);
685689
activity->load();
@@ -692,7 +696,7 @@ WalletController* BitcoinGUI::getWalletController()
692696

693697
void BitcoinGUI::addWallet(WalletModel* walletModel)
694698
{
695-
if (!walletFrame) return;
699+
if (!walletFrame || !m_wallet_controller) return;
696700

697701
WalletView* wallet_view = new WalletView(walletModel, platformStyle, walletFrame);
698702
if (!walletFrame->addView(wallet_view)) return;
@@ -742,7 +746,7 @@ void BitcoinGUI::removeWallet(WalletModel* walletModel)
742746

743747
void BitcoinGUI::setCurrentWallet(WalletModel* wallet_model)
744748
{
745-
if (!walletFrame) return;
749+
if (!walletFrame || !m_wallet_controller) return;
746750
walletFrame->setCurrentWallet(wallet_model);
747751
for (int index = 0; index < m_wallet_selector->count(); ++index) {
748752
if (m_wallet_selector->itemData(index).value<WalletModel*>() == wallet_model) {

src/qt/sendcoinsdialog.cpp

+9-4
Original file line numberDiff line numberDiff line change
@@ -600,10 +600,15 @@ SendCoinsEntry *SendCoinsDialog::addEntry()
600600
entry->clear();
601601
entry->setFocus();
602602
ui->scrollAreaWidgetContents->resize(ui->scrollAreaWidgetContents->sizeHint());
603-
qApp->processEvents();
604-
QScrollBar* bar = ui->scrollArea->verticalScrollBar();
605-
if(bar)
606-
bar->setSliderPosition(bar->maximum());
603+
604+
// Scroll to the newly added entry on a QueuedConnection because Qt doesn't
605+
// adjust the scroll area and scrollbar immediately when the widget is added.
606+
// Invoking on a DirectConnection will only scroll to the second-to-last entry.
607+
QMetaObject::invokeMethod(ui->scrollArea, [this] {
608+
if (ui->scrollArea->verticalScrollBar()) {
609+
ui->scrollArea->verticalScrollBar()->setValue(ui->scrollArea->verticalScrollBar()->maximum());
610+
}
611+
}, Qt::QueuedConnection);
607612

608613
updateTabsAndLabels();
609614
return entry;

src/qt/test/wallettests.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ void TestGUI(interfaces::Node& node)
212212
QCOMPARE(transactionTableModel->rowCount({}), 105);
213213
uint256 txid1 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 5 * COIN, /*rbf=*/false);
214214
uint256 txid2 = SendCoins(*wallet.get(), sendCoinsDialog, PKHash(), 10 * COIN, /*rbf=*/true);
215+
// Transaction table model updates on a QueuedConnection, so process events to ensure it's updated.
216+
qApp->processEvents();
215217
QCOMPARE(transactionTableModel->rowCount({}), 107);
216218
QVERIFY(FindTx(*transactionTableModel, txid1).isValid());
217219
QVERIFY(FindTx(*transactionTableModel, txid2).isValid());

0 commit comments

Comments
 (0)