1
mirror of https://github.com/monero-project/monero-gui synced 2024-12-30 22:56:24 +01:00

Merge pull request #249

7fd80a1 async close: make sure curretWallet isn't used after shutdown started (Jaquee)
eb97bda code clean up and wallet close consistency (Jaquee)
ead9bd7 WalletManager: lock wallet while closing (Jaquee)
This commit is contained in:
Riccardo Spagni 2016-12-14 23:27:29 +02:00
commit 6a132da785
No known key found for this signature in database
GPG Key ID: 55432DF31CCD4FCD
5 changed files with 69 additions and 81 deletions

View File

@ -109,30 +109,8 @@ ApplicationWindow {
ctrlPressed = false ctrlPressed = false
} }
function mousePressed(obj, mouseX, mouseY) { function mousePressed(obj, mouseX, mouseY) {}
// if(obj.objectName === "appWindow") function mouseReleased(obj, mouseX, mouseY) {}
// obj = rootItem
// var tmp = rootItem.mapFromItem(obj, mouseX, mouseY)
// if(tmp !== undefined) {
// mouseX = tmp.x
// mouseY = tmp.y
// }
// if(currentItem !== undefined) {
// var tmp_x = rootItem.mapToItem(currentItem, mouseX, mouseY).x
// var tmp_y = rootItem.mapToItem(currentItem, mouseX, mouseY).y
// if(!currentItem.containsPoint(tmp_x, tmp_y)) {
// currentItem.hide()
// currentItem = undefined
// }
// }
}
function mouseReleased(obj, mouseX, mouseY) {
}
function openWalletFromFile(){ function openWalletFromFile(){
persistentSettings.restore_height = 0 persistentSettings.restore_height = 0
@ -153,22 +131,11 @@ ApplicationWindow {
translationManager.setLanguage(locale.split("_")[0]); translationManager.setLanguage(locale.split("_")[0]);
} }
// disconnect handlers before connecting // If currentWallet exists, we're just switching daemon - close/reopen wallet
middlePanel.paymentClicked.disconnect(handlePayment); if (typeof currentWallet !== "undefined" && currentWallet !== null) {
// TODO: remove if statement when PR #111 is merged console.log("Daemon change - closing " + currentWallet)
if(typeof(handleCheckPayment) !== "undefined") { walletManager.closeWalletAsync();
middlePanel.checkPaymentClicked.disconnect(handleCheckPayment); currentWallet = undefined
}
middlePanel.paymentClicked.connect(handlePayment);
middlePanel.sweepUnmixableClicked.connect(handleSweepUnmixable);
// basicPanel.paymentClicked.connect(handlePayment);
middlePanel.checkPaymentClicked.connect(handleCheckPayment);
// currentWallet is defined on daemon address change - close/reopen
// TODO: strict comparison here (!==) causes crash after passwordDialog on previously crashed unsynced wallets
if (currentWallet != undefined) {
console.log("closing currentWallet")
walletManager.closeWallet(currentWallet);
} else { } else {
// set page to transfer if not changing daemon // set page to transfer if not changing daemon
@ -216,7 +183,11 @@ ApplicationWindow {
currentWallet.moneyReceived.disconnect(onWalletMoneyReceived) currentWallet.moneyReceived.disconnect(onWalletMoneyReceived)
currentWallet.transactionCreated.disconnect(onTransactionCreated) currentWallet.transactionCreated.disconnect(onTransactionCreated)
currentWallet.connectionStatusChanged.disconnect(onWalletConnectionStatusChanged) currentWallet.connectionStatusChanged.disconnect(onWalletConnectionStatusChanged)
middlePanel.paymentClicked.disconnect(handlePayment);
middlePanel.sweepUnmixableClicked.disconnect(handleSweepUnmixable);
middlePanel.checkPaymentClicked.disconnect(handleCheckPayment);
// connect handlers
currentWallet.refreshed.connect(onWalletRefresh) currentWallet.refreshed.connect(onWalletRefresh)
currentWallet.updated.connect(onWalletUpdate) currentWallet.updated.connect(onWalletUpdate)
currentWallet.newBlock.connect(onWalletNewBlock) currentWallet.newBlock.connect(onWalletNewBlock)
@ -224,7 +195,9 @@ ApplicationWindow {
currentWallet.moneyReceived.connect(onWalletMoneyReceived) currentWallet.moneyReceived.connect(onWalletMoneyReceived)
currentWallet.transactionCreated.connect(onTransactionCreated) currentWallet.transactionCreated.connect(onTransactionCreated)
currentWallet.connectionStatusChanged.connect(onWalletConnectionStatusChanged) currentWallet.connectionStatusChanged.connect(onWalletConnectionStatusChanged)
middlePanel.paymentClicked.connect(handlePayment);
middlePanel.sweepUnmixableClicked.connect(handleSweepUnmixable);
middlePanel.checkPaymentClicked.connect(handleCheckPayment);
console.log("initializing with daemon address: ", persistentSettings.daemon_address) console.log("initializing with daemon address: ", persistentSettings.daemon_address)
console.log("Recovering from seed: ", persistentSettings.is_recovering) console.log("Recovering from seed: ", persistentSettings.is_recovering)
@ -248,7 +221,9 @@ ApplicationWindow {
if (appWindow.password === '') { if (appWindow.password === '') {
console.error("Error opening wallet with empty password: ", wallet.errorString); console.error("Error opening wallet with empty password: ", wallet.errorString);
console.log("closing wallet async : " + wallet.address) console.log("closing wallet async : " + wallet.address)
walletManager.closeWalletAsync(wallet) walletManager.closeWalletAsync()
currentWallet = undefined
// try to open wallet with password; // try to open wallet with password;
passwordDialog.open(wallet.path); passwordDialog.open(wallet.path);
} else { } else {
@ -259,7 +234,8 @@ ApplicationWindow {
informationPopup.text = qsTr("Couldn't open wallet: ") + wallet.errorString; informationPopup.text = qsTr("Couldn't open wallet: ") + wallet.errorString;
informationPopup.icon = StandardIcon.Critical informationPopup.icon = StandardIcon.Critical
console.log("closing wallet async : " + wallet.address) console.log("closing wallet async : " + wallet.address)
walletManager.closeWalletAsync(wallet); walletManager.closeWalletAsync();
currentWallet = undefined
informationPopup.open() informationPopup.open()
informationPopup.onCloseCallback = function() { informationPopup.onCloseCallback = function() {
passwordDialog.open(wallet.path) passwordDialog.open(wallet.path)
@ -619,7 +595,6 @@ ApplicationWindow {
middlePanel.enabled = enable; middlePanel.enabled = enable;
leftPanel.enabled = enable; leftPanel.enabled = enable;
rightPanel.enabled = enable; rightPanel.enabled = enable;
// basicPanel.enabled = enable;
} }
function showProcessingSplash(message) { function showProcessingSplash(message) {
@ -640,14 +615,10 @@ ApplicationWindow {
function showWizard(){ function showWizard(){
walletInitialized = false; walletInitialized = false;
splashCounter = 0; splashCounter = 0;
// we can't close async here. Gui crashes if wallet is open walletManager.closeWalletAsync();
if (currentWallet != undefined) { currentWallet = undefined
walletManager.closeWallet(currentWallet);
currentWallet = undefined
}
wizard.restart(); wizard.restart();
rootItem.state = "wizard" rootItem.state = "wizard"
} }
@ -702,8 +673,6 @@ ApplicationWindow {
property bool is_recovering : false property bool is_recovering : false
} }
// TODO: replace with customized popups
// Information dialog // Information dialog
StandardDialog { StandardDialog {
// dynamically change onclose handler // dynamically change onclose handler
@ -748,7 +717,6 @@ ApplicationWindow {
id: passwordDialog id: passwordDialog
onAccepted: { onAccepted: {
appWindow.currentWallet = null
appWindow.initialize(); appWindow.initialize();
} }
onRejected: { onRejected: {
@ -1036,12 +1004,8 @@ ApplicationWindow {
} }
} }
onClosing: { onClosing: {
// Make sure wallet is closed before app exit (~Wallet() isn't always invoked) // Close wallet
// Daemon shutdown is handled with signal/slot in main.cpp walletManager.closeWallet();
if (currentWallet != undefined) {
walletManager.closeWallet(currentWallet);
currentWallet = undefined
}
// Stop daemon // Stop daemon
daemonManager.stop(); daemonManager.stop();
} }

View File

@ -7,10 +7,11 @@
#include <QDebug> #include <QDebug>
#include <QUrl> #include <QUrl>
#include <QtConcurrent/QtConcurrent> #include <QtConcurrent/QtConcurrent>
#include <QMutex>
#include <QMutexLocker>
WalletManager * WalletManager::m_instance = nullptr; WalletManager * WalletManager::m_instance = nullptr;
WalletManager *WalletManager::instance() WalletManager *WalletManager::instance()
{ {
if (!m_instance) { if (!m_instance) {
@ -23,27 +24,37 @@ WalletManager *WalletManager::instance()
Wallet *WalletManager::createWallet(const QString &path, const QString &password, Wallet *WalletManager::createWallet(const QString &path, const QString &password,
const QString &language, bool testnet) const QString &language, bool testnet)
{ {
QMutexLocker locker(&m_mutex);
if (m_currentWallet) {
qDebug() << "Closing open m_currentWallet" << m_currentWallet;
delete m_currentWallet;
}
Monero::Wallet * w = m_pimpl->createWallet(path.toStdString(), password.toStdString(), Monero::Wallet * w = m_pimpl->createWallet(path.toStdString(), password.toStdString(),
language.toStdString(), testnet); language.toStdString(), testnet);
Wallet * wallet = new Wallet(w); m_currentWallet = new Wallet(w);
return wallet; return m_currentWallet;
} }
Wallet *WalletManager::openWallet(const QString &path, const QString &password, bool testnet) Wallet *WalletManager::openWallet(const QString &path, const QString &password, bool testnet)
{ {
QMutexLocker locker(&m_mutex);
if (m_currentWallet) {
qDebug() << "Closing open m_currentWallet" << m_currentWallet;
delete m_currentWallet;
}
qDebug("%s: opening wallet at %s, testnet = %d ", qDebug("%s: opening wallet at %s, testnet = %d ",
__PRETTY_FUNCTION__, qPrintable(path), testnet); __PRETTY_FUNCTION__, qPrintable(path), testnet);
Monero::Wallet * w = m_pimpl->openWallet(path.toStdString(), password.toStdString(), testnet); Monero::Wallet * w = m_pimpl->openWallet(path.toStdString(), password.toStdString(), testnet);
qDebug("%s: opened wallet: %s, status: %d", __PRETTY_FUNCTION__, w->address().c_str(), w->status()); qDebug("%s: opened wallet: %s, status: %d", __PRETTY_FUNCTION__, w->address().c_str(), w->status());
Wallet * wallet = new Wallet(w); m_currentWallet = new Wallet(w);
// move wallet to the GUI thread. Otherwise it wont be emitting signals // move wallet to the GUI thread. Otherwise it wont be emitting signals
if (wallet->thread() != qApp->thread()) { if (m_currentWallet->thread() != qApp->thread()) {
wallet->moveToThread(qApp->thread()); m_currentWallet->moveToThread(qApp->thread());
} }
return wallet; return m_currentWallet;
} }
void WalletManager::openWalletAsync(const QString &path, const QString &password, bool testnet) void WalletManager::openWalletAsync(const QString &path, const QString &password, bool testnet)
@ -63,23 +74,34 @@ void WalletManager::openWalletAsync(const QString &path, const QString &password
Wallet *WalletManager::recoveryWallet(const QString &path, const QString &memo, bool testnet, quint64 restoreHeight) Wallet *WalletManager::recoveryWallet(const QString &path, const QString &memo, bool testnet, quint64 restoreHeight)
{ {
QMutexLocker locker(&m_mutex);
if (m_currentWallet) {
qDebug() << "Closing open m_currentWallet" << m_currentWallet;
delete m_currentWallet;
}
Monero::Wallet * w = m_pimpl->recoveryWallet(path.toStdString(), memo.toStdString(), testnet, restoreHeight); Monero::Wallet * w = m_pimpl->recoveryWallet(path.toStdString(), memo.toStdString(), testnet, restoreHeight);
Wallet * wallet = new Wallet(w); m_currentWallet = new Wallet(w);
return wallet; return m_currentWallet;
} }
QString WalletManager::closeWallet(Wallet *wallet) QString WalletManager::closeWallet()
{ {
QString result = wallet->address(); QMutexLocker locker(&m_mutex);
delete wallet; QString result;
if (m_currentWallet) {
result = m_currentWallet->address();
delete m_currentWallet;
} else {
qCritical() << "Trying to close non existing wallet " << m_currentWallet;
result = "0";
}
return result; return result;
} }
void WalletManager::closeWalletAsync(Wallet *wallet) void WalletManager::closeWalletAsync()
{ {
QFuture<QString> future = QtConcurrent::run(this, &WalletManager::closeWallet, QFuture<QString> future = QtConcurrent::run(this, &WalletManager::closeWallet);
wallet);
QFutureWatcher<QString> * watcher = new QFutureWatcher<QString>(); QFutureWatcher<QString> * watcher = new QFutureWatcher<QString>();
watcher->setFuture(future); watcher->setFuture(future);

View File

@ -4,6 +4,8 @@
#include <QObject> #include <QObject>
#include <QUrl> #include <QUrl>
#include <wallet/wallet2_api.h> #include <wallet/wallet2_api.h>
#include <QMutex>
#include <QPointer>
class Wallet; class Wallet;
namespace Monero { namespace Monero {
@ -52,17 +54,15 @@ public:
bool testnet = false, quint64 restoreHeight = 0); bool testnet = false, quint64 restoreHeight = 0);
/*! /*!
* \brief closeWallet - closes wallet and frees memory * \brief closeWallet - closes current open wallet and frees memory
* \param wallet
* \return wallet address * \return wallet address
*/ */
Q_INVOKABLE QString closeWallet(Wallet * wallet); Q_INVOKABLE QString closeWallet();
/*! /*!
* \brief closeWalletAsync - asynchronous version of "closeWallet" * \brief closeWalletAsync - asynchronous version of "closeWallet"
* \param wallet - wallet pointer;
*/ */
Q_INVOKABLE void closeWalletAsync(Wallet * wallet); Q_INVOKABLE void closeWalletAsync();
//! checks is given filename is a wallet; //! checks is given filename is a wallet;
Q_INVOKABLE bool walletExists(const QString &path) const; Q_INVOKABLE bool walletExists(const QString &path) const;
@ -125,6 +125,8 @@ private:
explicit WalletManager(QObject *parent = 0); explicit WalletManager(QObject *parent = 0);
static WalletManager * m_instance; static WalletManager * m_instance;
Monero::WalletManager * m_pimpl; Monero::WalletManager * m_pimpl;
QMutex m_mutex;
QPointer<Wallet> m_currentWallet;
}; };

View File

@ -78,7 +78,7 @@ Item {
// Always delete the wallet object before creating new - we could be stepping back from recovering wallet // Always delete the wallet object before creating new - we could be stepping back from recovering wallet
if (typeof settingsObject.wallet !== 'undefined') { if (typeof settingsObject.wallet !== 'undefined') {
settingsObject.wallet.destroy() walletManager.closeWallet()
console.log("deleting wallet") console.log("deleting wallet")
} }

View File

@ -79,7 +79,7 @@ Item {
settingsObject['wallet'] = wallet; settingsObject['wallet'] = wallet;
settingsObject['is_recovering'] = true; settingsObject['is_recovering'] = true;
} else { } else {
walletManager.closeWallet(wallet); walletManager.closeWallet();
} }
return success; return success;
} }