diff options
author | Lars Knoll <lars.knoll@qt.io> | 2020-11-20 13:51:16 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-06-17 09:27:47 +0000 |
commit | e41c100460126d8cb044f11db73b52d6b80f9309 (patch) | |
tree | be80d2ba9c18a3560539148d83a6ccc87c7b1667 /src/corelib/kernel/qobject_p.h | |
parent | b6323f0c7ba24a4ad5daa3535fcc9d6b285cfe28 (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 'src/corelib/kernel/qobject_p.h')
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 8dd29e05ce..4d5543d34a 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -257,7 +257,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); @@ -304,8 +307,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 |