[Development] Removing the global static QObject from QPixmapCache

Sze Howe Koh szehowe.koh at gmail.com
Sun May 30 07:28:40 CEST 2021


== Issue ==
There is a rule that "QCoreApplication should be the first QObject
created and last destroyed" [1]. However, there exists a violation to
this rule in Qt's internals -- QPixmapCache uses an internal global
static QObject (a QPMCache, to be precise) [2].

If initialized, the QPMCache outlives the QGuiApplication and gets
destroyed when the program/library is unloaded. This violates the rule
above.

This also causes problems when the QGuiApplication is created in a
std::thread instead of in main() (e.g. when a non-Qt application loads
a Qt-based plugin to display a GUI) -- The QPMCache destructor is run
by the wrong thread, which produces a warning, " QObject::~QObject:
Timers cannot be stopped from another thread ". There are also reports
that this can cause crashes [3][4].


== Proposal ==
QPMCache does not need the thread-safe initialization offered by
QGlobalStatic, since it can only be used from the Qt GUI thread. It
should also not outlive QGuiApplication.

So, I propose replacing QGlobalStatic<QPMCache> with
QPointer<QPMCache> as a simple self-cleaning singleton, and replacing
access to the global variable with QPMCache::instance():

    QPointer<QPMCache> pm_cache;

    QPMCache *QPMCache::instance() {
        if (!pm_cache && qGuiApp && !qGuiApp->closingDown()) {
            Q_ASSERT_X(QThread::currentThread() == qGuiApp->thread(),
"QPixmapCache initialization", "QPixmap can only be accessed from the
GUI thread");

            pm_cache = new QPMCache;
            connect(qGuiApp, &QGuiApplication::aboutToQuit, [] {
                QPixmapCache::clear();
                pm_cache->deleteLater();
            });
        }
        return pm_cache;
    }


I believe this approach should also take care of the ancient QTBUG-21807 [5]

Thoughts?


Regards,
Sze-Howe

[1] https://bugreports.qt.io/browse/QTBUG-71545?focusedCommentId=430042#comment-430042
[2] https://code.woboq.org/qt5/qtbase/src/gui/image/qpixmapcache.cpp.html#pm_cache
[3] https://forum.qt.io/topic/126128/qapplication-in-std-thread
[4] https://forum.qt.io/topic/126168/global-static-qpixmapcache-in-qt-internals
[5] https://bugreports.qt.io/browse/QTBUG-21807


More information about the Development mailing list