tst_QThread: add a test for self-cancellation

Doesn't test anything, just that it doesn't crash.

Turns out we have a race between thread cancellation and normal exit
(filed as QTBUG-127008). Worked around by adding an infinite loop to
run(), after terminate().

Android doesn't support cancellation at all, and our Windows
implementation hits QTBUG-127050, so skip the test on those
platforms.

Pick-to: 6.7 6.5 6.2 5.15
Change-Id: I47a635a31caaf116d3688f31b9b5c5875e9765f5
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit a9f7e75a2647732ff998f1c0d112682dbd5c4e28)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Marc Mutz 2024-07-08 11:39:43 +02:00 committed by Qt Cherry-pick Bot
parent 0d7b42d92b
commit 1c53afb774

View File

@ -100,6 +100,7 @@ private slots:
void terminateAndPrematureDestruction();
void terminateAndDoubleDestruction();
void terminateSelfStressTest();
void bindingListCleanupAfterDelete();
};
@ -1935,6 +1936,53 @@ void tst_QThread::terminateAndDoubleDestruction()
TestObject obj;
}
void tst_QThread::terminateSelfStressTest()
{
// This simply tests that QThread::terminate() doesn't crash or causes
// sanitizer reports when a thread cancels itself.
#ifdef Q_OS_ANDROID
QSKIP("Android cannot cancel threads");
#endif
#ifdef Q_OS_WIN
QSKIP("QTBUG-127050");
#endif
struct Thread : QThread {
void run() override {
terminate();
while (true) sleep(1ns); // QTBUG-127008
}
};
{
// first, try with one:
Thread t;
t.start();
QVERIFY(t.wait(10s));
}
constexpr QThread::Priority priorities[] = {
QThread::IdlePriority,
QThread::LowestPriority,
QThread::LowPriority,
QThread::NormalPriority,
QThread::HighPriority,
QThread::HighestPriority,
QThread::TimeCriticalPriority,
QThread::InheritPriority,
};
QVarLengthArray<Thread, 1024> threads(3 * QThread::idealThreadCount());
size_t i = 0;
for (Thread &t : threads)
t.start(priorities[i++ % std::size(priorities)]);
for (Thread &t : threads)
QVERIFY2(t.wait(60s), QByteArray::number(&t - threads.data()).constData());
}
void tst_QThread::bindingListCleanupAfterDelete()
{
QThread t;