[PictureLoader] Fix worker thread shutdown and cross-thread cache clearing

clearNetworkCache() ran directly on the UI thread while the worker thread
owned the disk cache and redirect cache, racing cache reads/writes. Make it
a worker-thread slot invoked via a blocking queued call when the thread is
running, so the 'Cached card pictures have been reset.' message is truthful.

The worker thread was also never quit()/wait()ed: both destructors only
deleteLater'd their objects, so Qt warned 'QThread: Destroyed while thread
is still running' and leaked a running loop at exit. Wire the worker's
finished() signal to its own deleteLater() (canonical worker-object
pattern), add shutdownThread() to stop the loop, and let CardPictureLoader
destroy the QThread only after wait() has returned.
This commit is contained in:
Lukas Brübach 2026-09-12 22:50:19 +02:00 committed by GitHub
parent 3bd118fae9
commit a28ab11126
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 72 additions and 5 deletions

View file

@ -11,6 +11,7 @@
#include <QDir>
#include <QFileInfo>
#include <QMainWindow>
#include <QMetaObject>
#include <QMovie>
#include <QNetworkRequest>
#include <QPainter>
@ -58,7 +59,14 @@ CardPictureLoader::CardPictureLoader() : QObject(nullptr)
CardPictureLoader::~CardPictureLoader()
{
worker->deleteLater();
if (worker) {
// Capture the thread first: shutdownThread() blocks until the worker has been freed by the
// finished() -> deleteLater chain, after which the worker pointer must not be dereferenced.
QThread *pictureLoaderThread = worker->workerThread();
worker->shutdownThread();
worker = nullptr;
delete pictureLoaderThread;
}
}
void CardPictureLoader::getCardBackPixmap(QPixmap &pixmap, QSize size)
@ -457,7 +465,15 @@ void CardPictureLoader::clearPixmapCache()
void CardPictureLoader::clearNetworkCache()
{
getInstance().worker->clearNetworkCache();
auto &worker = *getInstance().worker;
// The disk cache and redirect cache are owned by the worker thread; clearing them from the
// UI thread would race with the worker's cache reads/writes. Block until the worker thread
// has executed the clear so the "Cached card pictures have been reset." message is truthful.
if (worker.isRunning()) {
QMetaObject::invokeMethod(&worker, "clearNetworkCache", Qt::BlockingQueuedConnection);
} else {
worker.clearNetworkCache();
}
}
void CardPictureLoader::cacheCardPixmaps(const QList<ExactCard> &cards)