gui: macOS, do not process dock icon actions during shutdown

As the 'QMenuBar' is created without a parent window in MacOS, the
app crashes when the user presses the shutdown button and, right
after it, triggers any action in the menu bar.

This happens because the QMenuBar is manually deleted in the
BitcoinGUI destructor but the events attached to it children
actions are not disconnected, so QActions events such us the
'QMenu::aboutToShow' could try to access null pointers.

Instead of guarding every single QAction pointer inside the
QMenu::aboutToShow slot, or manually disconnecting all
registered events in the destructor, we can check if a
shutdown was requested and discard the event.

The 'node' field is a ref whose memory is held by the
main application class, so it is safe to use here. Events
are disconnected prior destructing the main application object.

Furthermore, the 'MacDockIconHandler::dockIconClicked' signal
can make the app crash during shutdown for the very same
reason. The 'show()' call triggers the 'QApplication::focusWindowChanged'
event, which is connected to the 'minimize_action' QAction,
which is also part of the app menu bar, which could no longer exist.
pull/28561/head
furszy 1 year ago
parent 238d29aff9
commit e14cc8fc69
No known key found for this signature in database
GPG Key ID: 5DD23CCC686AA623

@ -864,6 +864,7 @@ void BitcoinGUI::createTrayIconMenu()
// Note: On macOS, the Dock icon is used to provide the tray's functionality.
MacDockIconHandler* dockIconHandler = MacDockIconHandler::instance();
connect(dockIconHandler, &MacDockIconHandler::dockIconClicked, [this] {
if (m_node.shutdownRequested()) return; // nothing to show, node is shutting down.
show();
activateWindow();
});
@ -875,6 +876,8 @@ void BitcoinGUI::createTrayIconMenu()
// See https://bugreports.qt.io/browse/QTBUG-91697
trayIconMenu.get(), &QMenu::aboutToShow,
[this, show_hide_action, send_action, receive_action, sign_action, verify_action, options_action, node_window_action, quit_action] {
if (m_node.shutdownRequested()) return; // nothing to do, node is shutting down.
if (show_hide_action) show_hide_action->setText(
(!isHidden() && !isMinimized() && !GUIUtil::isObscured(this)) ?
tr("&Hide") :

Loading…
Cancel
Save