summaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-11-20 13:51:16 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-06-17 09:27:45 +0000
commitbbc2076b7d13e68a9c31de2e837538f7f0ee1ecc (patch)
tree9ef4496ace40ac2bc6c776e100c6c6e6f9701492 /tests/auto
parente224f1e2323c677cc13120829a0bef9d545891c6 (diff)
Fix crash in concurrent disconnect
This does not fix all data races that we have in the system yet. One major issue is the virtual disconnectNotify(), that can be called from any thread and thus is inherently problematic, as it can collide with the object getting destroyed at the same time in another thread. Task-number: QTBUG-88248 Change-Id: I9d841eb363b7e4f0de1657aeb8f5340d0fd55190 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> (cherry picked from commit 71b4d4f150bc3c904a5aceec37513ddc3cd1c150) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/other/qobjectrace/tst_qobjectrace.cpp49
1 files changed, 49 insertions, 0 deletions
diff --git a/tests/auto/other/qobjectrace/tst_qobjectrace.cpp b/tests/auto/other/qobjectrace/tst_qobjectrace.cpp
index ac33fa3ec3..093b4d2476 100644
--- a/tests/auto/other/qobjectrace/tst_qobjectrace.cpp
+++ b/tests/auto/other/qobjectrace/tst_qobjectrace.cpp
@@ -49,6 +49,7 @@ private slots:
void destroyRace();
void blockingQueuedDestroyRace();
void disconnectRace();
+ void disconnectRace2();
};
class RaceObject : public QObject
@@ -562,5 +563,53 @@ void tst_QObjectRace::disconnectRace()
QCOMPARE(countedStructObjectsCount.loadRelaxed(), 0u);
}
+void tst_QObjectRace::disconnectRace2()
+{
+ enum { IterationCount = 100, ConnectionCount = 100, YieldCount = 100 };
+
+ QAtomicPointer<MyObject> ptr;
+ QSemaphore createSemaphore(0);
+ QSemaphore proceedSemaphore(0);
+
+ std::unique_ptr<QThread> t1(QThread::create([&]() {
+ for (int i = 0; i < IterationCount; ++i) {
+ MyObject sender;
+ ptr.storeRelease(&sender);
+ createSemaphore.release();
+ proceedSemaphore.acquire();
+ ptr.storeRelaxed(nullptr);
+ for (int i = 0; i < YieldCount; ++i)
+ QThread::yieldCurrentThread();
+ }
+ }));
+ t1->start();
+
+
+ std::unique_ptr<QThread> t2(QThread::create([&]() {
+ auto connections = std::make_unique<QMetaObject::Connection[]>(ConnectionCount);
+ for (int i = 0; i < IterationCount; ++i) {
+ MyObject receiver;
+ MyObject *sender = nullptr;
+
+ createSemaphore.acquire();
+
+ while (!(sender = ptr.loadAcquire()))
+ ;
+
+ for (int i = 0; i < ConnectionCount; ++i)
+ connections[i] = QObject::connect(sender, &MyObject::signal1, &receiver, &MyObject::slot1);
+
+ proceedSemaphore.release();
+
+ for (int i = 0; i < ConnectionCount; ++i)
+ QObject::disconnect(connections[i]);
+ }
+ }));
+ t2->start();
+
+ t1->wait();
+ t2->wait();
+}
+
QTEST_MAIN(tst_QObjectRace)
#include "tst_qobjectrace.moc"