What changed, and why it matters
This commit fixes a minor behavior bug: if a user interrupted Bitcoin Core while it was starting up, the program would wrongly report that it had failed (non-zero exit code). The change makes an interrupted startup return a normal success exit code, matching how an interrupt is treated after startup is complete. It also updates the graphical (GUI) startup path to recognize when the user asked for shutdown during initialization.
No security action required. Treat as a normal bug-fix patch. Operators relying on exit codes for startup-failure detection should note that user-initiated shutdown during init will no longer produce EXIT_FAILURE.
Security signals we found
No memory corruption, injection, or cryptographic weakness present in diff
Change is purely a correctness/UX fix for process exit-code behavior
No privilege boundary crossed; no attacker-controlled input parsed differently
Evidence from the diff
In AppInitMain, two early-return paths that fire when ShutdownRequested(node) is true now return true instead of false. Previously, returning false propagated up the call stack and caused the process to exit with EXIT_FAILURE. Returning true lets the normal shutdown path run and yields a zero exit code, consistent with post-init interrupt handling. The Qt GUI startup code in BitcoinApplication::initializeResult was refactored so that either a failed init or a requested shutdown triggers requestShutdown(), while successful init continues to set up the main window. This prevents the GUI from treating a user-requested shutdown during init as an error condition.
Changed components
src/init.cpp: AppInitMain early-exit paths on ShutdownRequestedsrc/qt/bitcoin.cpp: BitcoinApplication::initializeResult GUI startup handlingInspect captured patch +41 / −40
diff --git a/src/init.cpp b/src/init.cpp
index f2af858e..d435a216 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1830,7 +1830,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// requested to kill the GUI during the last operation. If so, exit.
if (ShutdownRequested(node)) {
LogInfo("Shutdown requested. Exiting.");
- return false;
+ return true;
}
ChainstateManager& chainman = *Assert(node.chainman);
@@ -2006,7 +2006,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
}
if (ShutdownRequested(node)) {
- return false;
+ return true;
}
// ********************************************************* Step 12: start node
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 54e1747c..92c815fe 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -380,53 +380,54 @@ void BitcoinApplication::initializeResult(bool success, interfaces::BlockAndHead
{
qDebug() << __func__ << ": Initialization result: " << success;
- if (success) {
- delete m_splash;
- m_splash = nullptr;
+ if (!success || m_node->shutdownRequested()) {
+ requestShutdown();
+ return;
+ }
+
+ delete m_splash;
+ m_splash = nullptr;
- // Log this only after AppInitMain finishes, as then logging setup is guaranteed complete
- qInfo() << "Platform customization:" << platformStyle->getName();
- clientModel = new ClientModel(node(), optionsModel);
- window->setClientModel(clientModel, &tip_info);
+ // Log this only after AppInitMain finishes, as then logging setup is guaranteed complete
+ qInfo() << "Platform customization:" << platformStyle->getName();
+ clientModel = new ClientModel(node(), optionsModel);
+ window->setClientModel(clientModel, &tip_info);
- // If '-min' option passed, start window minimized (iconified) or minimized to tray
- bool start_minimized = gArgs.GetBoolArg("-min", false);
+ // If '-min' option passed, start window minimized (iconified) or minimized to tray
+ bool start_minimized = gArgs.GetBoolArg("-min", false);
#ifdef ENABLE_WALLET
- if (WalletModel::isWalletEnabled()) {
- m_wallet_controller = new WalletController(*clientModel, platformStyle, this);
- window->setWalletController(m_wallet_controller, /*show_loading_minimized=*/start_minimized);
- if (paymentServer) {
- paymentServer->setOptionsModel(optionsModel);
- }
+ if (WalletModel::isWalletEnabled()) {
+ m_wallet_controller = new WalletController(*clientModel, platformStyle, this);
+ window->setWalletController(m_wallet_controller, /*show_loading_minimized=*/start_minimized);
+ if (paymentServer) {
+ paymentServer->setOptionsModel(optionsModel);
}
+ }
#endif // ENABLE_WALLET
- // Show or minimize window
- if (!start_minimized) {
- window->show();
- } else if (clientModel->getOptionsModel()->getMinimizeToTray() && window->hasTrayIcon()) {
- // do nothing as the window is managed by the tray icon
- } else {
- window->showMinimized();
- }
- Q_EMIT windowShown(window);
+ // Show or minimize window
+ if (!start_minimized) {
+ window->show();
+ } else if (clientModel->getOptionsModel()->getMinimizeToTray() && window->hasTrayIcon()) {
+ // do nothing as the window is managed by the tray icon
+ } else {
+ window->showMinimized();
+ }
+ Q_EMIT windowShown(window);
#ifdef ENABLE_WALLET
- // Now that initialization/startup is done, process any command-line
- // bitcoin: URIs or payment requests:
- if (paymentServer) {
- connect(paymentServer, &PaymentServer::receivedPaymentRequest, window, &BitcoinGUI::handlePaymentRequest);
- connect(window, &BitcoinGUI::receivedURI, paymentServer, &PaymentServer::handleURIOrFile);
- connect(paymentServer, &PaymentServer::message, [this](const QString& title, const QString& message, unsigned int style) {
- window->message(title, message, style);
- });
- QTimer::singleShot(100ms, paymentServer, &PaymentServer::uiReady);
- }
-#endif
- pollShutdownTimer->start(SHUTDOWN_POLLING_DELAY);
- } else {
- requestShutdown();
+ // Now that initialization/startup is done, process any command-line
+ // bitcoin: URIs or payment requests:
+ if (paymentServer) {
+ connect(paymentServer, &PaymentServer::receivedPaymentRequest, window, &BitcoinGUI::handlePaymentRequest);
+ connect(window, &BitcoinGUI::receivedURI, paymentServer, &PaymentServer::handleURIOrFile);
+ connect(paymentServer, &PaymentServer::message, [this](const QString& title, const QString& message, unsigned int style) {
+ window->message(title, message, style);
+ });
+ QTimer::singleShot(100ms, paymentServer, &PaymentServer::uiReady);
}
+#endif
+ pollShutdownTimer->start(SHUTDOWN_POLLING_DELAY);
}
void BitcoinApplication::handleRunawayException(const QString &message)
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.