[Client] Only quit on update when the shutdown actually ran

MainWindow::closeEvent has a static re-entrancy guard that returns early on a
second close event, leaving it in its default accepted state. DlgUpdate reached
from a nested event loop while a shutdown prompt was up could then get close()
== true with no shutdown work done (no settings flush, no tab shutdown) and tear
down the process behind an unanswered prompt.

Add MainWindow::closeForUpdate(), which reports false when a close is already in
progress or was vetoed, and gate the update-exit on it.
This commit is contained in:
Lukas Brübach 2026-09-21 18:59:30 +02:00
parent adc74bd57c
commit 00dcc0d5c1
3 changed files with 25 additions and 4 deletions

View file

@ -246,10 +246,12 @@ void DlgUpdate::downloadSuccessful(const QUrl &filepath)
// Close the main window synchronously so file locks are released before the NSIS installer
// (already launched) starts replacing files. This also flushes settings and shuts down the
// tabs, but only when the close is actually accepted: MainWindow may veto it for a running
// card DB update, an open game, or an unsaved deck. In that case keep running so the user
// can resolve the blocker, and tell them the installer is already waiting.
// card DB update, an open game, or an unsaved deck, and closeForUpdate() also reports a
// close already in progress (reached from a nested event loop while a shutdown prompt is
// up). Only quit when the shutdown really ran - otherwise keep running so the user can
// resolve the blocker, and tell them the installer is already waiting.
if (auto *window = qobject_cast<MainWindow *>(parent())) {
if (window->close()) {
if (window->closeForUpdate()) {
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
} else {
QMessageBox::warning(this, tr("Update"),