diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2023-03-27 22:19:40 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2023-04-26 04:55:47 -0300 |
commit | b9394b48c1b42e0ef834315ca4f89161a5c12ae7 (patch) | |
tree | f2be1386b53fc904118ea43bb505221e8d8c5ecb /tests/auto/corelib/kernel/qcoreapplication | |
parent | ebd27ff654a5973be404183d3dd517bd13ff06a0 (diff) |
tst_QCoreApplication: ensure that theMainThread has expected states
The expected states are:
- nothing sets theMainThread before main()
- theMainThread is reset when the last QObject (the QCoreApplication in
the test) is destroyed
The GUI version of this test appears to leak a lot of QObjects. By the
time this function runs, theMainThread's QThreadData still has a
refcount of 66 on Linux/XCB. The Windows non-GUI version also
failed. Neither situation was investigated to see why objects are
getting leaked.
Pick-to: 6.5
Change-Id: Idd5e1bb52be047d7b4fffffd17507d9e6ef08743
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'tests/auto/corelib/kernel/qcoreapplication')
-rw-r--r-- | tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp | 40 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h | 1 |
2 files changed, 38 insertions, 3 deletions
diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp index 46d52c2340..edba67bf46 100644 --- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp +++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp @@ -1034,16 +1034,50 @@ void tst_QCoreApplication::addRemoveLibPaths() } #endif +static bool theMainThreadIsSet() +{ + // QCoreApplicationPrivate::mainThread() has a Q_ASSERT we'd trigger + return QCoreApplicationPrivate::theMainThread.loadRelaxed() != nullptr; +} + +static bool theMainThreadWasUnset = !theMainThreadIsSet(); // global static +void tst_QCoreApplication::theMainThread() +{ + QVERIFY2(theMainThreadWasUnset, "Something set the theMainThread before main()"); + QVERIFY(theMainThreadIsSet()); // we have at LEAST one QObject alive: tst_QCoreApplication + + int argc = 1; + char *argv[] = { const_cast<char*>(QTest::currentAppName()) }; + TestApplication app(argc, argv); + QVERIFY(QCoreApplicationPrivate::theMainThread.loadRelaxed()); + QCOMPARE(QCoreApplicationPrivate::theMainThread.loadRelaxed(), thread()); + QCOMPARE(app.thread(), thread()); + QCOMPARE(app.thread(), QThread::currentThread()); +} + static void createQObjectOnDestruction() { - // Make sure that we can create a QObject after the last QObject has been - // destroyed (especially after QCoreApplication has). - // + // Make sure that we can create a QObject (and thus have an associated + // QThread) after the last QObject has been destroyed (especially after + // QCoreApplication has). + +#if !defined(QT_QGUIAPPLICATIONTEST) && !defined(Q_OS_WIN) + // QCoreApplicationData's global static destructor has run and cleaned up + // the QAdoptedThrad. + if (theMainThreadIsSet()) + qFatal("theMainThreadIsSet() returned true; some QObject must have leaked"); +#endif + // Before the fixes, this would cause a dangling pointer dereference. If // the problem comes back, it's possible that the following causes no // effect. QObject obj; obj.thread()->setProperty("testing", 1); + if (!theMainThreadIsSet()) + qFatal("theMainThreadIsSet() returned false"); + + // because we created a QObject after QCoreApplicationData was destroyed, + // the QAdoptedThread won't get cleaned up } Q_DESTRUCTOR_FUNCTION(createQObjectOnDestruction) diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h index 0894b64f33..91d9324db4 100644 --- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h +++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h @@ -44,6 +44,7 @@ private slots: #if QT_CONFIG(library) void addRemoveLibPaths(); #endif + void theMainThread(); }; #endif // TST_QCOREAPPLICATION_H |