mirror of
https://github.com/monero-project/monero-gui.git
synced 2025-01-11 05:14:34 +00:00
Merge pull request #492
8021037
pause refresh while starting daemon + startup timeout (Jaquee)df60c81
add start/pauseRefresh() (Jaquee)2ed59f4
Daemon manager improvements (Jaquee)
This commit is contained in:
commit
75bb620cb6
6 changed files with 130 additions and 14 deletions
25
main.qml
25
main.qml
|
@ -236,7 +236,6 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
function connectWallet(wallet) {
|
function connectWallet(wallet) {
|
||||||
showProcessingSplash("Please wait...")
|
|
||||||
currentWallet = wallet
|
currentWallet = wallet
|
||||||
updateSyncing(false)
|
updateSyncing(false)
|
||||||
|
|
||||||
|
@ -342,9 +341,6 @@ ApplicationWindow {
|
||||||
|
|
||||||
function onWalletRefresh() {
|
function onWalletRefresh() {
|
||||||
console.log(">>> wallet refreshed")
|
console.log(">>> wallet refreshed")
|
||||||
if (splash.visible) {
|
|
||||||
hideProcessingSplash()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Daemon connected
|
// Daemon connected
|
||||||
leftPanel.networkStatus.connected = currentWallet.connected()
|
leftPanel.networkStatus.connected = currentWallet.connected()
|
||||||
|
@ -385,6 +381,9 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
function startDaemon(flags){
|
function startDaemon(flags){
|
||||||
|
// Pause refresh while starting daemon
|
||||||
|
currentWallet.pauseRefresh();
|
||||||
|
|
||||||
appWindow.showProcessingSplash(qsTr("Waiting for daemon to start..."))
|
appWindow.showProcessingSplash(qsTr("Waiting for daemon to start..."))
|
||||||
daemonManager.start(flags, persistentSettings.testnet);
|
daemonManager.start(flags, persistentSettings.testnet);
|
||||||
persistentSettings.daemonFlags = flags
|
persistentSettings.daemonFlags = flags
|
||||||
|
@ -399,6 +398,9 @@ ApplicationWindow {
|
||||||
console.log("daemon started");
|
console.log("daemon started");
|
||||||
daemonRunning = true;
|
daemonRunning = true;
|
||||||
hideProcessingSplash();
|
hideProcessingSplash();
|
||||||
|
currentWallet.connected(true);
|
||||||
|
// resume refresh
|
||||||
|
currentWallet.startRefresh();
|
||||||
}
|
}
|
||||||
function onDaemonStopped(){
|
function onDaemonStopped(){
|
||||||
console.log("daemon stopped");
|
console.log("daemon stopped");
|
||||||
|
@ -407,6 +409,19 @@ ApplicationWindow {
|
||||||
currentWallet.connected(true);
|
currentWallet.connected(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onDaemonStartFailure(){
|
||||||
|
console.log("daemon start failed");
|
||||||
|
hideProcessingSplash();
|
||||||
|
// resume refresh
|
||||||
|
currentWallet.startRefresh();
|
||||||
|
daemonRunning = false;
|
||||||
|
informationPopup.title = qsTr("Daemon failed to start") + translationManager.emptyString;
|
||||||
|
informationPopup.text = qsTr("Please check your wallet and daemon log for errors. You can also try to start %1 manually.").arg((isWindows)? "monerod.exe" : "monerod")
|
||||||
|
informationPopup.icon = StandardIcon.Critical
|
||||||
|
informationPopup.onCloseCallback = null
|
||||||
|
informationPopup.open();
|
||||||
|
}
|
||||||
|
|
||||||
function onWalletNewBlock(blockHeight, targetHeight) {
|
function onWalletNewBlock(blockHeight, targetHeight) {
|
||||||
// Update progress bar
|
// Update progress bar
|
||||||
var remaining = targetHeight - blockHeight;
|
var remaining = targetHeight - blockHeight;
|
||||||
|
@ -769,6 +784,7 @@ ApplicationWindow {
|
||||||
walletManager.walletClosed.connect(onWalletClosed);
|
walletManager.walletClosed.connect(onWalletClosed);
|
||||||
|
|
||||||
daemonManager.daemonStarted.connect(onDaemonStarted);
|
daemonManager.daemonStarted.connect(onDaemonStarted);
|
||||||
|
daemonManager.daemonStartFailure.connect(onDaemonStartFailure);
|
||||||
daemonManager.daemonStopped.connect(onDaemonStopped);
|
daemonManager.daemonStopped.connect(onDaemonStopped);
|
||||||
|
|
||||||
if(!walletsFound()) {
|
if(!walletsFound()) {
|
||||||
|
@ -1239,6 +1255,7 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
onClosing: {
|
onClosing: {
|
||||||
// Close wallet non async on exit
|
// Close wallet non async on exit
|
||||||
|
daemonManager.exit();
|
||||||
walletManager.closeWallet();
|
walletManager.closeWallet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -407,7 +407,7 @@ Rectangle {
|
||||||
console.log("Settings page loaded");
|
console.log("Settings page loaded");
|
||||||
initSettings();
|
initSettings();
|
||||||
viewOnly = currentWallet.viewOnly;
|
viewOnly = currentWallet.viewOnly;
|
||||||
daemonManager.running(persistentSettings.testnet)
|
appWindow.daemonRunning = daemonManager.running(persistentSettings.testnet)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fires only once
|
// fires only once
|
||||||
|
|
|
@ -7,6 +7,11 @@
|
||||||
#include <QtConcurrent/QtConcurrent>
|
#include <QtConcurrent/QtConcurrent>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
#include <QTime>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static const int DAEMON_START_TIMEOUT_SECONDS = 30;
|
||||||
|
}
|
||||||
|
|
||||||
DaemonManager * DaemonManager::m_instance = nullptr;
|
DaemonManager * DaemonManager::m_instance = nullptr;
|
||||||
QStringList DaemonManager::m_clArgs;
|
QStringList DaemonManager::m_clArgs;
|
||||||
|
@ -69,23 +74,93 @@ bool DaemonManager::start(const QString &flags, bool testnet)
|
||||||
|
|
||||||
if (!started) {
|
if (!started) {
|
||||||
qDebug() << "Daemon start error: " + m_daemon->errorString();
|
qDebug() << "Daemon start error: " + m_daemon->errorString();
|
||||||
} else {
|
emit daemonStartFailure();
|
||||||
emit daemonStarted();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return started;
|
// Start start watcher
|
||||||
|
QFuture<bool> future = QtConcurrent::run(this, &DaemonManager::startWatcher, testnet);
|
||||||
|
QFutureWatcher<bool> * watcher = new QFutureWatcher<bool>();
|
||||||
|
connect(watcher, &QFutureWatcher<bool>::finished,
|
||||||
|
this, [this, watcher]() {
|
||||||
|
QFuture<bool> future = watcher->future();
|
||||||
|
watcher->deleteLater();
|
||||||
|
if(future.result())
|
||||||
|
emit daemonStarted();
|
||||||
|
else
|
||||||
|
emit daemonStartFailure();
|
||||||
|
});
|
||||||
|
watcher->setFuture(future);
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DaemonManager::stop(bool testnet)
|
bool DaemonManager::stop(bool testnet)
|
||||||
{
|
{
|
||||||
QString message;
|
QString message;
|
||||||
bool stopped = sendCommand("exit",testnet,message);
|
sendCommand("exit",testnet,message);
|
||||||
qDebug() << message;
|
qDebug() << message;
|
||||||
if(stopped)
|
|
||||||
|
// Start stop watcher - Will kill if not shutting down
|
||||||
|
QFuture<bool> future = QtConcurrent::run(this, &DaemonManager::stopWatcher, testnet);
|
||||||
|
QFutureWatcher<bool> * watcher = new QFutureWatcher<bool>();
|
||||||
|
connect(watcher, &QFutureWatcher<bool>::finished,
|
||||||
|
this, [this, watcher]() {
|
||||||
|
QFuture<bool> future = watcher->future();
|
||||||
|
watcher->deleteLater();
|
||||||
|
if(future.result()) {
|
||||||
emit daemonStopped();
|
emit daemonStopped();
|
||||||
return stopped;
|
}
|
||||||
|
});
|
||||||
|
watcher->setFuture(future);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DaemonManager::startWatcher(bool testnet) const
|
||||||
|
{
|
||||||
|
// Check if daemon is started every 2 seconds
|
||||||
|
QTime timer;
|
||||||
|
timer.restart();
|
||||||
|
while(true && !m_app_exit && timer.elapsed() / 1000 < DAEMON_START_TIMEOUT_SECONDS ) {
|
||||||
|
QThread::sleep(2);
|
||||||
|
if(!running(testnet)) {
|
||||||
|
qDebug() << "daemon not running. checking again in 2 seconds.";
|
||||||
|
} else {
|
||||||
|
qDebug() << "daemon is started. Waiting 5 seconds to let daemon catch up";
|
||||||
|
QThread::sleep(5);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DaemonManager::stopWatcher(bool testnet) const
|
||||||
|
{
|
||||||
|
// Check if daemon is running every 2 seconds. Kill if still running after 10 seconds
|
||||||
|
int counter = 0;
|
||||||
|
while(true && !m_app_exit) {
|
||||||
|
QThread::sleep(2);
|
||||||
|
counter++;
|
||||||
|
if(running(testnet)) {
|
||||||
|
qDebug() << "Daemon still running. " << counter;
|
||||||
|
if(counter >= 5) {
|
||||||
|
qDebug() << "Killing it! ";
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
QProcess::execute("taskkill /F /IM monerod.exe");
|
||||||
|
#else
|
||||||
|
QProcess::execute("pkill monerod");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DaemonManager::stateChanged(QProcess::ProcessState state)
|
void DaemonManager::stateChanged(QProcess::ProcessState state)
|
||||||
{
|
{
|
||||||
qDebug() << "STATE CHANGED: " << state;
|
qDebug() << "STATE CHANGED: " << state;
|
||||||
|
@ -124,10 +199,8 @@ bool DaemonManager::running(bool testnet) const
|
||||||
// `./monerod status` returns BUSY when syncing.
|
// `./monerod status` returns BUSY when syncing.
|
||||||
// Treat busy as connected, until fixed upstream.
|
// Treat busy as connected, until fixed upstream.
|
||||||
if (status.contains("Height:") || status.contains("BUSY") ) {
|
if (status.contains("Height:") || status.contains("BUSY") ) {
|
||||||
emit daemonStarted();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
emit daemonStopped();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool DaemonManager::sendCommand(const QString &cmd,bool testnet) const
|
bool DaemonManager::sendCommand(const QString &cmd,bool testnet) const
|
||||||
|
@ -155,6 +228,12 @@ bool DaemonManager::sendCommand(const QString &cmd,bool testnet, QString &messag
|
||||||
return started;
|
return started;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DaemonManager::exit()
|
||||||
|
{
|
||||||
|
qDebug("DaemonManager: exit()");
|
||||||
|
m_app_exit = true;
|
||||||
|
}
|
||||||
|
|
||||||
DaemonManager::DaemonManager(QObject *parent)
|
DaemonManager::DaemonManager(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,12 +20,17 @@ public:
|
||||||
Q_INVOKABLE bool running(bool testnet) const;
|
Q_INVOKABLE bool running(bool testnet) const;
|
||||||
// Send daemon command from qml and prints output in console window.
|
// Send daemon command from qml and prints output in console window.
|
||||||
Q_INVOKABLE bool sendCommand(const QString &cmd, bool testnet) const;
|
Q_INVOKABLE bool sendCommand(const QString &cmd, bool testnet) const;
|
||||||
|
Q_INVOKABLE void exit();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool sendCommand(const QString &cmd, bool testnet, QString &message) const;
|
bool sendCommand(const QString &cmd, bool testnet, QString &message) const;
|
||||||
|
bool startWatcher(bool testnet) const;
|
||||||
|
bool stopWatcher(bool testnet) const;
|
||||||
signals:
|
signals:
|
||||||
void daemonStarted() const;
|
void daemonStarted() const;
|
||||||
void daemonStopped() const;
|
void daemonStopped() const;
|
||||||
|
void daemonStartFailure() const;
|
||||||
void daemonConsoleUpdated(QString message) const;
|
void daemonConsoleUpdated(QString message) const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -41,6 +46,7 @@ private:
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
QString m_monerod;
|
QString m_monerod;
|
||||||
bool m_has_daemon = true;
|
bool m_has_daemon = true;
|
||||||
|
bool m_app_exit = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -302,6 +302,16 @@ int Wallet::autoRefreshInterval() const
|
||||||
return m_walletImpl->autoRefreshInterval();
|
return m_walletImpl->autoRefreshInterval();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Wallet::startRefresh() const
|
||||||
|
{
|
||||||
|
m_walletImpl->startRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Wallet::pauseRefresh() const
|
||||||
|
{
|
||||||
|
m_walletImpl->pauseRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id,
|
PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id,
|
||||||
quint64 amount, quint32 mixin_count,
|
quint64 amount, quint32 mixin_count,
|
||||||
PendingTransaction::Priority priority)
|
PendingTransaction::Priority priority)
|
||||||
|
|
|
@ -146,6 +146,10 @@ public:
|
||||||
//! return auto-refresh interval in seconds
|
//! return auto-refresh interval in seconds
|
||||||
Q_INVOKABLE int autoRefreshInterval() const;
|
Q_INVOKABLE int autoRefreshInterval() const;
|
||||||
|
|
||||||
|
// pause/resume refresh
|
||||||
|
Q_INVOKABLE void startRefresh() const;
|
||||||
|
Q_INVOKABLE void pauseRefresh() const;
|
||||||
|
|
||||||
//! creates transaction
|
//! creates transaction
|
||||||
Q_INVOKABLE PendingTransaction * createTransaction(const QString &dst_addr, const QString &payment_id,
|
Q_INVOKABLE PendingTransaction * createTransaction(const QString &dst_addr, const QString &payment_id,
|
||||||
quint64 amount, quint32 mixin_count,
|
quint64 amount, quint32 mixin_count,
|
||||||
|
|
Loading…
Reference in a new issue