summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qobject_p.h
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-11-20 13:51:16 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2021-06-17 08:56:22 +0200
commit71b4d4f150bc3c904a5aceec37513ddc3cd1c150 (patch)
treeb0e0214ef81ed700b0f0d1fcbd576dee1ba6ad9a /src/corelib/kernel/qobject_p.h
parent556fc646cfac4dca43a34f5c4a4f7e6e3ef9104d (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. Pick-to: 6.2 6.1 5.15 Task-number: QTBUG-88248 Change-Id: I9d841eb363b7e4f0de1657aeb8f5340d0fd55190 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/kernel/qobject_p.h')
-rw-r--r--src/corelib/kernel/qobject_p.h16
1 files changed, 13 insertions, 3 deletions
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index f945b79ca1..539818ac1d 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -271,7 +271,10 @@ public:
~ConnectionData()
{
- deleteOrphaned(orphaned.loadRelaxed());
+ Q_ASSERT(ref.loadRelaxed() == 0);
+ auto *c = orphaned.fetchAndStoreRelaxed(nullptr);
+ if (c)
+ deleteOrphaned(c);
SignalVector *v = signalVector.loadRelaxed();
if (v)
free(v);
@@ -318,8 +321,15 @@ public:
signalVector.storeRelaxed(newVector);
if (vector) {
- vector->nextInOrphanList = orphaned.loadRelaxed();
- orphaned.storeRelaxed(ConnectionOrSignalVector::fromSignalVector(vector));
+ Connection *o = nullptr;
+ /* No ABA issue here: When adding a node, we only care about the list head, it doesn't
+ * matter if the tail changes.
+ */
+ do {
+ o = orphaned.loadRelaxed();
+ vector->nextInOrphanList = o;
+ } while (!orphaned.testAndSetRelease(o, ConnectionOrSignalVector::fromSignalVector(vector)));
+
}
}
int signalVectorCount() const