mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-05 09:33:25 -08:00
[Settings] Delete update channels at shutdown
SettingsCache owns the stable and beta update channels as raw pointers, and each owns a QNetworkAccessManager, so the process leaves QtNetwork objects alive past QApplication teardown. Delete them from a QCoreApplication::aboutToQuit handler instead of the destructor: SettingsCache is a Q_GLOBAL_STATIC, so ~SettingsCache() runs during static teardown, after QApplication is gone, and destroying the network managers at that point is the post-application window that ASan reports. The hook is installed on the first instance() call that has an application object, since the first access may predate it.
This commit is contained in:
parent
8551e22b2d
commit
70f9947c0f
2 changed files with 32 additions and 1 deletions
|
|
@ -6,6 +6,7 @@
|
|||
#include "shortcuts_settings.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
|
|
@ -47,7 +48,32 @@ Q_GLOBAL_STATIC(SettingsCache, settingsCache)
|
|||
|
||||
SettingsCache &SettingsCache::instance()
|
||||
{
|
||||
return *settingsCache; // returns a QT managed singleton reference
|
||||
SettingsCache &cache = *settingsCache; // returns a QT managed singleton reference
|
||||
// The release channels own QNetworkAccessManagers, which must be destroyed
|
||||
// while the application object is alive. ~SettingsCache() runs during
|
||||
// static teardown, after QApplication is gone, so hook the application's
|
||||
// shutdown instead. Retried here because the first access may predate the
|
||||
// application object.
|
||||
cache.installShutdownHook();
|
||||
return cache;
|
||||
}
|
||||
|
||||
void SettingsCache::installShutdownHook()
|
||||
{
|
||||
if (shutdownHookInstalled) {
|
||||
return;
|
||||
}
|
||||
QCoreApplication *application = QCoreApplication::instance();
|
||||
if (application == nullptr) {
|
||||
return;
|
||||
}
|
||||
connect(application, &QCoreApplication::aboutToQuit, this, [this] {
|
||||
for (ReleaseChannel *releaseChannel : std::as_const(releaseChannels)) {
|
||||
delete releaseChannel;
|
||||
}
|
||||
releaseChannels.clear();
|
||||
});
|
||||
shutdownHookInstalled = true;
|
||||
}
|
||||
|
||||
QString SettingsCache::getDataPath()
|
||||
|
|
|
|||
|
|
@ -90,8 +90,13 @@ private:
|
|||
QString themeName;
|
||||
|
||||
QList<ReleaseChannel *> releaseChannels;
|
||||
bool shutdownHookInstalled = false;
|
||||
bool isPortableBuild;
|
||||
|
||||
// Connects the aboutToQuit handler that deletes the release channels while
|
||||
// the application object is still alive; a no-op before it exists.
|
||||
void installShutdownHook();
|
||||
|
||||
[[nodiscard]] QString getSafeConfigPath(QString configEntry, QString defaultPath) const;
|
||||
[[nodiscard]] QString getSafeConfigFilePath(QString configEntry, QString defaultPath) const;
|
||||
void loadPaths();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue