Skip to content

Commit a965f2b

Browse files
committed
gui: fix crash when closing wallet
The crash occurs because 'WalletController::removeAndDeleteWallet' is called twice for the same wallet model: first in the GUI's button connected function 'WalletController::closeWallet', and then again when the backend emits the 'WalletModel::unload' signal. This causes the issue because 'removeAndDeleteWallet' inlines an erase(std::remove()). So, if 'std::remove' returns an iterator to the end (indicating the element wasn't found because it was already erased), the subsequent call to 'erase' leads to an undefined behavior.
1 parent cf0120f commit a965f2b

File tree

2 files changed

+13
-8
lines changed

2 files changed

+13
-8
lines changed

src/qt/walletcontroller.cpp

+10-8
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ std::map<std::string, std::pair<bool, std::string>> WalletController::listWallet
7979
return wallets;
8080
}
8181

82+
void WalletController::removeWallet(WalletModel* wallet_model)
83+
{
84+
// Once the wallet is successfully removed from the node, the model will emit the 'WalletModel::unload' signal.
85+
// This signal is already connected and will complete the removal of the view from the GUI.
86+
// Look at 'WalletController::getOrCreateWallet' for the signal connection.
87+
wallet_model->wallet().remove();
88+
}
89+
8290
void WalletController::closeWallet(WalletModel* wallet_model, QWidget* parent)
8391
{
8492
QMessageBox box(parent);
@@ -89,10 +97,7 @@ void WalletController::closeWallet(WalletModel* wallet_model, QWidget* parent)
8997
box.setDefaultButton(QMessageBox::Yes);
9098
if (box.exec() != QMessageBox::Yes) return;
9199

92-
// First remove wallet from node.
93-
wallet_model->wallet().remove();
94-
// Now release the model.
95-
removeAndDeleteWallet(wallet_model);
100+
removeWallet(wallet_model);
96101
}
97102

98103
void WalletController::closeAllWallets(QWidget* parent)
@@ -105,11 +110,8 @@ void WalletController::closeAllWallets(QWidget* parent)
105110

106111
QMutexLocker locker(&m_mutex);
107112
for (WalletModel* wallet_model : m_wallets) {
108-
wallet_model->wallet().remove();
109-
Q_EMIT walletRemoved(wallet_model);
110-
delete wallet_model;
113+
removeWallet(wallet_model);
111114
}
112-
m_wallets.clear();
113115
}
114116

115117
WalletModel* WalletController::getOrCreateWallet(std::unique_ptr<interfaces::Wallet> wallet)

src/qt/walletcontroller.h

+3
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ class WalletController : public QObject
8585

8686
friend class WalletControllerActivity;
8787
friend class MigrateWalletActivity;
88+
89+
//! Starts the wallet closure procedure
90+
void removeWallet(WalletModel* wallet_model);
8891
};
8992

9093
class WalletControllerActivity : public QObject

0 commit comments

Comments
 (0)