diff options
Diffstat (limited to 'src/qt/bitcoin.cpp')
-rw-r--r-- | src/qt/bitcoin.cpp | 166 |
1 files changed, 84 insertions, 82 deletions
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 9e6cf56d31..f6ea147ddb 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -7,12 +7,19 @@ #endif #include <qt/bitcoin.h> -#include <qt/bitcoingui.h> #include <chainparams.h> +#include <init.h> +#include <interfaces/handler.h> +#include <interfaces/node.h> +#include <node/context.h> +#include <node/ui_interface.h> +#include <noui.h> +#include <qt/bitcoingui.h> #include <qt/clientmodel.h> #include <qt/guiconstants.h> #include <qt/guiutil.h> +#include <qt/initexecutor.h> #include <qt/intro.h> #include <qt/networkstyle.h> #include <qt/optionsmodel.h> @@ -20,6 +27,12 @@ #include <qt/splashscreen.h> #include <qt/utilitydialog.h> #include <qt/winshutdownmonitor.h> +#include <uint256.h> +#include <util/string.h> +#include <util/system.h> +#include <util/threadnames.h> +#include <util/translation.h> +#include <validation.h> #ifdef ENABLE_WALLET #include <qt/paymentserver.h> @@ -27,18 +40,6 @@ #include <qt/walletmodel.h> #endif // ENABLE_WALLET -#include <init.h> -#include <interfaces/handler.h> -#include <interfaces/node.h> -#include <node/context.h> -#include <node/ui_interface.h> -#include <noui.h> -#include <uint256.h> -#include <util/system.h> -#include <util/threadnames.h> -#include <util/translation.h> -#include <validation.h> - #include <boost/signals2/connection.hpp> #include <memory> @@ -144,56 +145,61 @@ static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTrans QApplication::installTranslator(&translator); } -/* qDebug() message handler --> debug.log */ -void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &msg) +static bool InitSettings() { - Q_UNUSED(context); - if (type == QtDebugMsg) { - LogPrint(BCLog::QT, "GUI: %s\n", msg.toStdString()); - } else { - LogPrintf("GUI: %s\n", msg.toStdString()); + if (!gArgs.GetSettingsPath()) { + return true; // Do nothing if settings file disabled. } -} - -BitcoinCore::BitcoinCore(interfaces::Node& node) : - QObject(), m_node(node) -{ -} -void BitcoinCore::handleRunawayException(const std::exception *e) -{ - PrintExceptionContinue(e, "Runaway exception"); - Q_EMIT runawayException(QString::fromStdString(m_node.getWarnings().translated)); -} + std::vector<std::string> errors; + if (!gArgs.ReadSettingsFile(&errors)) { + bilingual_str error = _("Settings file could not be read"); + InitError(Untranslated(strprintf("%s:\n%s\n", error.original, MakeUnorderedList(errors)))); + + QMessageBox messagebox(QMessageBox::Critical, PACKAGE_NAME, QString::fromStdString(strprintf("%s.", error.translated)), QMessageBox::Reset | QMessageBox::Abort); + /*: Explanatory text shown on startup when the settings file cannot be read. + Prompts user to make a choice between resetting or aborting. */ + messagebox.setInformativeText(QObject::tr("Do you want to reset settings to default values, or to abort without making changes?")); + messagebox.setDetailedText(QString::fromStdString(MakeUnorderedList(errors))); + messagebox.setTextFormat(Qt::PlainText); + messagebox.setDefaultButton(QMessageBox::Reset); + switch (messagebox.exec()) { + case QMessageBox::Reset: + break; + case QMessageBox::Abort: + return false; + default: + assert(false); + } + } -void BitcoinCore::initialize() -{ - try - { - util::ThreadRename("qt-init"); - qDebug() << __func__ << ": Running initialization in thread"; - interfaces::BlockAndHeaderTipInfo tip_info; - bool rv = m_node.appInitMain(&tip_info); - Q_EMIT initializeResult(rv, tip_info); - } catch (const std::exception& e) { - handleRunawayException(&e); - } catch (...) { - handleRunawayException(nullptr); + errors.clear(); + if (!gArgs.WriteSettingsFile(&errors)) { + bilingual_str error = _("Settings file could not be written"); + InitError(Untranslated(strprintf("%s:\n%s\n", error.original, MakeUnorderedList(errors)))); + + QMessageBox messagebox(QMessageBox::Critical, PACKAGE_NAME, QString::fromStdString(strprintf("%s.", error.translated)), QMessageBox::Ok); + /*: Explanatory text shown on startup when the settings file could not be written. + Prompts user to check that we have the ability to write to the file. + Explains that the user has the option of running without a settings file.*/ + messagebox.setInformativeText(QObject::tr("A fatal error occurred. Check that settings file is writable, or try running with -nosettings.")); + messagebox.setDetailedText(QString::fromStdString(MakeUnorderedList(errors))); + messagebox.setTextFormat(Qt::PlainText); + messagebox.setDefaultButton(QMessageBox::Ok); + messagebox.exec(); + return false; } + return true; } -void BitcoinCore::shutdown() +/* qDebug() message handler --> debug.log */ +void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &msg) { - try - { - qDebug() << __func__ << ": Running Shutdown in thread"; - m_node.appShutdown(); - qDebug() << __func__ << ": Shutdown finished"; - Q_EMIT shutdownResult(); - } catch (const std::exception& e) { - handleRunawayException(&e); - } catch (...) { - handleRunawayException(nullptr); + Q_UNUSED(context); + if (type == QtDebugMsg) { + LogPrint(BCLog::QT, "GUI: %s\n", msg.toStdString()); + } else { + LogPrintf("GUI: %s\n", msg.toStdString()); } } @@ -202,7 +208,6 @@ static const char* qt_argv = "bitcoin-qt"; BitcoinApplication::BitcoinApplication(): QApplication(qt_argc, const_cast<char **>(&qt_argv)), - coreThread(nullptr), optionsModel(nullptr), clientModel(nullptr), window(nullptr), @@ -230,13 +235,7 @@ void BitcoinApplication::setupPlatformStyle() BitcoinApplication::~BitcoinApplication() { - if(coreThread) - { - qDebug() << __func__ << ": Stopping thread"; - coreThread->quit(); - coreThread->wait(); - qDebug() << __func__ << ": Stopped thread"; - } + m_executor.reset(); delete window; window = nullptr; @@ -291,22 +290,15 @@ bool BitcoinApplication::baseInitialize() void BitcoinApplication::startThread() { - if(coreThread) - return; - coreThread = new QThread(this); - BitcoinCore *executor = new BitcoinCore(node()); - executor->moveToThread(coreThread); + assert(!m_executor); + m_executor.emplace(node()); /* communication to and from thread */ - connect(executor, &BitcoinCore::initializeResult, this, &BitcoinApplication::initializeResult); - connect(executor, &BitcoinCore::shutdownResult, this, &BitcoinApplication::shutdownResult); - connect(executor, &BitcoinCore::runawayException, this, &BitcoinApplication::handleRunawayException); - connect(this, &BitcoinApplication::requestedInitialize, executor, &BitcoinCore::initialize); - connect(this, &BitcoinApplication::requestedShutdown, executor, &BitcoinCore::shutdown); - /* make sure executor object is deleted in its own thread */ - connect(coreThread, &QThread::finished, executor, &QObject::deleteLater); - - coreThread->start(); + connect(&m_executor.value(), &InitExecutor::initializeResult, this, &BitcoinApplication::initializeResult); + connect(&m_executor.value(), &InitExecutor::shutdownResult, this, &BitcoinApplication::shutdownResult); + connect(&m_executor.value(), &InitExecutor::runawayException, this, &BitcoinApplication::handleRunawayException); + connect(this, &BitcoinApplication::requestedInitialize, &m_executor.value(), &InitExecutor::initialize); + connect(this, &BitcoinApplication::requestedShutdown, &m_executor.value(), &InitExecutor::shutdown); } void BitcoinApplication::parameterSetup() @@ -339,7 +331,6 @@ void BitcoinApplication::requestShutdown() shutdownWindow.reset(ShutdownWindow::showShutdownWindow(window)); qDebug() << __func__ << ": Requesting shutdown"; - startThread(); window->hide(); // Must disconnect node signals otherwise current thread can deadlock since // no event loop is running. @@ -352,6 +343,17 @@ void BitcoinApplication::requestShutdown() window->setClientModel(nullptr); pollShutdownTimer->stop(); +#ifdef ENABLE_WALLET + // Delete wallet controller here manually, instead of relying on Qt object + // tracking (https://doc.qt.io/qt-5/objecttrees.html). This makes sure + // walletmodel m_handle_* notification handlers are deleted before wallets + // are unloaded, which can simplify wallet implementations. It also avoids + // these notifications having to be handled while GUI objects are being + // destroyed, making GUI code less fragile as well. + delete m_wallet_controller; + m_wallet_controller = nullptr; +#endif // ENABLE_WALLET + delete clientModel; clientModel = nullptr; @@ -490,7 +492,8 @@ int GuiMain(int argc, char* argv[]) /// 2. Parse command-line options. We do this after qt in order to show an error if there are problems parsing these // Command-line options take precedence: - SetupServerArgs(node_context); + node_context.args = &gArgs; + SetupServerArgs(gArgs); SetupUIArgs(gArgs); std::string error; if (!gArgs.ParseParameters(argc, argv, error)) { @@ -568,9 +571,8 @@ int GuiMain(int argc, char* argv[]) // Parse URIs on command line -- this can affect Params() PaymentServer::ipcParseCommandLine(argc, argv); #endif - if (!gArgs.InitSettings(error)) { - InitError(Untranslated(error)); - QMessageBox::critical(nullptr, PACKAGE_NAME, QObject::tr("Error initializing settings: %1").arg(QString::fromStdString(error))); + + if (!InitSettings()) { return EXIT_FAILURE; } |