summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/thread/qthread
diff options
context:
space:
mode:
authorVladimir Belyavsky <belyavskyv@gmail.com>2022-06-01 20:44:57 +0300
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2022-06-10 19:40:32 +0000
commit865212057b9f4e2809ebe42ec25c2d94d818cde7 (patch)
tree7b8e47cc643de10f50ce4a07eb4d9ffd5b4cf8e9 /tests/auto/corelib/thread/qthread
parente2f14e5be702f89e3d54153fd7511c02729e014e (diff)
Windows: fix DeferredDelete events processing on QThread::terminate()
On finishing/terminating a thread, when processing posted events, we need to consider QThread's own data instead of caller thread's data. Otherwise we can get into unexpected situations such as double destruction of an object, premature destruction, etc. Fixes: QTBUG-103922 Pick-to: 6.4 6.3 6.3.1 6.2 5.15 Change-Id: Idf77221ebbaa0b150ee2d0c296b51829ae8dc30e Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'tests/auto/corelib/thread/qthread')
-rw-r--r--tests/auto/corelib/thread/qthread/tst_qthread.cpp78
1 files changed, 78 insertions, 0 deletions
diff --git a/tests/auto/corelib/thread/qthread/tst_qthread.cpp b/tests/auto/corelib/thread/qthread/tst_qthread.cpp
index 125c969ea2..b5f2ebdabf 100644
--- a/tests/auto/corelib/thread/qthread/tst_qthread.cpp
+++ b/tests/auto/corelib/thread/qthread/tst_qthread.cpp
@@ -91,6 +91,9 @@ private slots:
void create();
void createDestruction();
void threadIdReuse();
+
+ void terminateAndPrematureDestruction();
+ void terminateAndDoubleDestruction();
};
enum { one_minute = 60 * 1000, five_minutes = 5 * one_minute };
@@ -1719,5 +1722,80 @@ void tst_QThread::threadIdReuse()
}
}
+class WaitToRun_Thread : public QThread
+{
+ Q_OBJECT
+public:
+ void run() override
+ {
+ emit running();
+ QThread::exec();
+ }
+
+Q_SIGNALS:
+ void running();
+};
+
+
+void tst_QThread::terminateAndPrematureDestruction()
+{
+ WaitToRun_Thread thread;
+ QSignalSpy spy(&thread, &WaitToRun_Thread::running);
+ thread.start();
+ QVERIFY(spy.wait(500));
+
+ QScopedPointer<QObject> obj(new QObject);
+ QPointer<QObject> pObj(obj.data());
+ obj->deleteLater();
+
+ thread.terminate();
+ QVERIFY2(pObj, "object was deleted prematurely!");
+ thread.wait(500);
+}
+
+void tst_QThread::terminateAndDoubleDestruction()
+{
+ class ChildObject : public QObject
+ {
+ public:
+ ChildObject(QObject *parent)
+ : QObject(parent)
+ {
+ QSignalSpy spy(&thread, &WaitToRun_Thread::running);
+ thread.start();
+ spy.wait(500);
+ }
+
+ ~ChildObject()
+ {
+ QVERIFY2(!inDestruction, "Double object destruction!");
+ inDestruction = true;
+ thread.terminate();
+ thread.wait(500);
+ }
+
+ bool inDestruction = false;
+ WaitToRun_Thread thread;
+ };
+
+ class TestObject : public QObject
+ {
+ public:
+ TestObject()
+ : child(new ChildObject(this))
+ {
+ }
+
+ ~TestObject()
+ {
+ child->deleteLater();
+ }
+
+ ChildObject *child = nullptr;
+ };
+
+ TestObject obj;
+}
+
QTEST_MAIN(tst_QThread)
#include "tst_qthread.moc"