Changeset View
Changeset View
Standalone View
Standalone View
src/qt/bitcoin.cpp
Show First 20 Lines • Show All 166 Lines • ▼ Show 20 Lines | |||||
* Allows running startup and shutdown in a different thread from the UI thread. | * Allows running startup and shutdown in a different thread from the UI thread. | ||||
*/ | */ | ||||
class BitcoinABC : public QObject { | class BitcoinABC : public QObject { | ||||
Q_OBJECT | Q_OBJECT | ||||
public: | public: | ||||
explicit BitcoinABC(interfaces::Node &node); | explicit BitcoinABC(interfaces::Node &node); | ||||
public Q_SLOTS: | public Q_SLOTS: | ||||
void initialize(Config *config, | void initialize(Config *config, RPCServer *rpcServer, | ||||
HTTPRPCRequestProcessor *httpRPCRequestProcessor); | HTTPRPCRequestProcessor *httpRPCRequestProcessor); | ||||
void shutdown(); | void shutdown(); | ||||
Q_SIGNALS: | Q_SIGNALS: | ||||
void initializeResult(bool success); | void initializeResult(bool success); | ||||
void shutdownResult(); | void shutdownResult(); | ||||
void runawayException(const QString &message); | void runawayException(const QString &message); | ||||
Show All 20 Lines | #endif | ||||
/// Create options model | /// Create options model | ||||
void createOptionsModel(bool resetSettings); | void createOptionsModel(bool resetSettings); | ||||
/// Create main window | /// Create main window | ||||
void createWindow(const Config *, const NetworkStyle *networkStyle); | void createWindow(const Config *, const NetworkStyle *networkStyle); | ||||
/// Create splash screen | /// Create splash screen | ||||
void createSplashScreen(const NetworkStyle *networkStyle); | void createSplashScreen(const NetworkStyle *networkStyle); | ||||
/// Request core initialization | /// Request core initialization | ||||
void requestInitialize(Config &config, | void requestInitialize(Config &config, RPCServer &rpcServer, | ||||
HTTPRPCRequestProcessor &httpRPCRequestProcessor); | HTTPRPCRequestProcessor &httpRPCRequestProcessor); | ||||
/// Request core shutdown | /// Request core shutdown | ||||
void requestShutdown(Config &config); | void requestShutdown(Config &config); | ||||
/// Get process return value | /// Get process return value | ||||
int getReturnValue() const { return returnValue; } | int getReturnValue() const { return returnValue; } | ||||
/// Get window identifier of QMainWindow (BitcoinGUI) | /// Get window identifier of QMainWindow (BitcoinGUI) | ||||
WId getMainWinId() const; | WId getMainWinId() const; | ||||
public Q_SLOTS: | public Q_SLOTS: | ||||
void initializeResult(bool success); | void initializeResult(bool success); | ||||
void shutdownResult(); | void shutdownResult(); | ||||
/// Handle runaway exceptions. Shows a message box with the problem and | /// Handle runaway exceptions. Shows a message box with the problem and | ||||
/// quits the program. | /// quits the program. | ||||
void handleRunawayException(const QString &message); | void handleRunawayException(const QString &message); | ||||
Q_SIGNALS: | Q_SIGNALS: | ||||
void requestedInitialize(Config *config, | void requestedInitialize(Config *config, RPCServer *rpcServer, | ||||
HTTPRPCRequestProcessor *httpRPCRequestProcessor); | HTTPRPCRequestProcessor *httpRPCRequestProcessor); | ||||
void requestedShutdown(); | void requestedShutdown(); | ||||
void stopThread(); | void stopThread(); | ||||
void splashFinished(QWidget *window); | void splashFinished(QWidget *window); | ||||
private: | private: | ||||
QThread *coreThread; | QThread *coreThread; | ||||
interfaces::Node &m_node; | interfaces::Node &m_node; | ||||
Show All 16 Lines | |||||
BitcoinABC::BitcoinABC(interfaces::Node &node) : QObject(), m_node(node) {} | BitcoinABC::BitcoinABC(interfaces::Node &node) : QObject(), m_node(node) {} | ||||
void BitcoinABC::handleRunawayException(const std::exception *e) { | void BitcoinABC::handleRunawayException(const std::exception *e) { | ||||
PrintExceptionContinue(e, "Runaway exception"); | PrintExceptionContinue(e, "Runaway exception"); | ||||
Q_EMIT runawayException(QString::fromStdString(m_node.getWarnings("gui"))); | Q_EMIT runawayException(QString::fromStdString(m_node.getWarnings("gui"))); | ||||
} | } | ||||
void BitcoinABC::initialize(Config *cfg, | void BitcoinABC::initialize(Config *config, RPCServer *rpcServer, | ||||
HTTPRPCRequestProcessor *httpRPCRequestProcessor) { | HTTPRPCRequestProcessor *httpRPCRequestProcessor) { | ||||
Config &config(*cfg); | |||||
try { | try { | ||||
qDebug() << __func__ << ": Running initialization in thread"; | qDebug() << __func__ << ": Running initialization in thread"; | ||||
bool rv = m_node.appInitMain(config, *httpRPCRequestProcessor); | bool rv = | ||||
m_node.appInitMain(*config, *rpcServer, *httpRPCRequestProcessor); | |||||
Q_EMIT initializeResult(rv); | Q_EMIT initializeResult(rv); | ||||
} catch (const std::exception &e) { | } catch (const std::exception &e) { | ||||
handleRunawayException(&e); | handleRunawayException(&e); | ||||
} catch (...) { | } catch (...) { | ||||
handleRunawayException(nullptr); | handleRunawayException(nullptr); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 108 Lines • ▼ Show 20 Lines | void BitcoinApplication::startThread() { | ||||
// code to copy-construct the parameter in question (Q_DECLARE_METATYPE | // code to copy-construct the parameter in question (Q_DECLARE_METATYPE | ||||
// and qRegisterMetaType generate this code). For the Config class, | // and qRegisterMetaType generate this code). For the Config class, | ||||
// which is noncopyable, we can't do this. So.. we have to pass | // which is noncopyable, we can't do this. So.. we have to pass | ||||
// pointers to Config around. Make sure Config &/Config * isn't a | // pointers to Config around. Make sure Config &/Config * isn't a | ||||
// temporary (eg it lives somewhere aside from the stack) or this will | // temporary (eg it lives somewhere aside from the stack) or this will | ||||
// crash because initialize() gets executed in another thread at some | // crash because initialize() gets executed in another thread at some | ||||
// unspecified time (after) requestedInitialize() is emitted! | // unspecified time (after) requestedInitialize() is emitted! | ||||
connect(this, | connect(this, | ||||
SIGNAL(requestedInitialize(Config *, HTTPRPCRequestProcessor *)), | SIGNAL(requestedInitialize(Config *, RPCServer *, | ||||
executor, SLOT(initialize(Config *, HTTPRPCRequestProcessor *))); | HTTPRPCRequestProcessor *)), | ||||
executor, | |||||
SLOT(initialize(Config *, RPCServer *, HTTPRPCRequestProcessor *))); | |||||
connect(this, SIGNAL(requestedShutdown()), executor, SLOT(shutdown())); | connect(this, SIGNAL(requestedShutdown()), executor, SLOT(shutdown())); | ||||
/* make sure executor object is deleted in its own thread */ | /* make sure executor object is deleted in its own thread */ | ||||
connect(this, SIGNAL(stopThread()), executor, SLOT(deleteLater())); | connect(this, SIGNAL(stopThread()), executor, SLOT(deleteLater())); | ||||
connect(this, SIGNAL(stopThread()), coreThread, SLOT(quit())); | connect(this, SIGNAL(stopThread()), coreThread, SLOT(quit())); | ||||
coreThread->start(); | coreThread->start(); | ||||
} | } | ||||
void BitcoinApplication::parameterSetup() { | void BitcoinApplication::parameterSetup() { | ||||
m_node.initLogging(); | m_node.initLogging(); | ||||
m_node.initParameterInteraction(); | m_node.initParameterInteraction(); | ||||
} | } | ||||
void BitcoinApplication::requestInitialize( | void BitcoinApplication::requestInitialize( | ||||
Config &config, HTTPRPCRequestProcessor &httpRPCRequestProcessor) { | Config &config, RPCServer &rpcServer, | ||||
HTTPRPCRequestProcessor &httpRPCRequestProcessor) { | |||||
qDebug() << __func__ << ": Requesting initialize"; | qDebug() << __func__ << ": Requesting initialize"; | ||||
startThread(); | startThread(); | ||||
// IMPORTANT: config must NOT be a reference to a temporary because below | // IMPORTANT: config must NOT be a reference to a temporary because below | ||||
// signal may be connected to a slot that will be executed as a queued | // signal may be connected to a slot that will be executed as a queued | ||||
// connection in another thread! | // connection in another thread! | ||||
Q_EMIT requestedInitialize(&config, &httpRPCRequestProcessor); | Q_EMIT requestedInitialize(&config, &rpcServer, &httpRPCRequestProcessor); | ||||
} | } | ||||
void BitcoinApplication::requestShutdown(Config &config) { | void BitcoinApplication::requestShutdown(Config &config) { | ||||
// Show a simple window indicating shutdown status. Do this first as some of | // Show a simple window indicating shutdown status. Do this first as some of | ||||
// the steps may take some time below, for example the RPC console may still | // the steps may take some time below, for example the RPC console may still | ||||
// be executing a command. | // be executing a command. | ||||
shutdownWindow.reset(ShutdownWindow::showShutdownWindow(window)); | shutdownWindow.reset(ShutdownWindow::showShutdownWindow(window)); | ||||
▲ Show 20 Lines • Show All 336 Lines • ▼ Show 20 Lines | #endif | ||||
HTTPRPCRequestProcessor httpRPCRequestProcessor(config, rpcServer); | HTTPRPCRequestProcessor httpRPCRequestProcessor(config, rpcServer); | ||||
try { | try { | ||||
app.createWindow(&config, networkStyle.data()); | app.createWindow(&config, networkStyle.data()); | ||||
// Perform base initialization before spinning up | // Perform base initialization before spinning up | ||||
// initialization/shutdown thread. This is acceptable because this | // initialization/shutdown thread. This is acceptable because this | ||||
// function only contains steps that are quick to execute, so the GUI | // function only contains steps that are quick to execute, so the GUI | ||||
// thread won't be held up. | // thread won't be held up. | ||||
if (!node->baseInitialize(config, rpcServer)) { | if (!node->baseInitialize(config)) { | ||||
// A dialog with detailed error will have been shown by InitError() | // A dialog with detailed error will have been shown by InitError() | ||||
return EXIT_FAILURE; | return EXIT_FAILURE; | ||||
} | } | ||||
app.requestInitialize(config, httpRPCRequestProcessor); | app.requestInitialize(config, rpcServer, httpRPCRequestProcessor); | ||||
#if defined(Q_OS_WIN) | #if defined(Q_OS_WIN) | ||||
WinShutdownMonitor::registerShutdownBlockReason( | WinShutdownMonitor::registerShutdownBlockReason( | ||||
QObject::tr("%1 didn't yet exit safely...") | QObject::tr("%1 didn't yet exit safely...") | ||||
.arg(QObject::tr(PACKAGE_NAME)), | .arg(QObject::tr(PACKAGE_NAME)), | ||||
(HWND)app.getMainWinId()); | (HWND)app.getMainWinId()); | ||||
#endif | #endif | ||||
app.exec(); | app.exec(); | ||||
app.requestShutdown(config); | app.requestShutdown(config); | ||||
Show All 14 Lines |