diff options
Diffstat (limited to 'src/corelib/kernel/qobject.cpp')
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index ea706b93a0..33afcaaa7e 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -70,6 +70,7 @@ #include <qtcore_tracepoints_p.h> #include <new> +#include <mutex> #include <ctype.h> #include <limits.h> @@ -405,11 +406,14 @@ void QObjectPrivate::ConnectionData::removeConnection(QObjectPrivate::Connection } -void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sender) +void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sender, LockPolicy lockPolicy) { + QBasicMutex *senderMutex = signalSlotLock(sender); ConnectionOrSignalVector *c = nullptr; { - QBasicMutexLocker l(signalSlotLock(sender)); + std::unique_lock<QBasicMutex> lock(*senderMutex, std::defer_lock_t{}); + if (lockPolicy == NeedToLock) + lock.lock(); if (ref.loadAcquire() > 1) return; @@ -419,7 +423,16 @@ void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sende c = orphaned.loadRelaxed(); orphaned.storeRelaxed(nullptr); } - deleteOrphaned(c); + if (c) { + // Deleting c might run arbitrary user code, so we must not hold the lock + if (lockPolicy == AlreadyLockedAndTemporarilyReleasingLock) { + senderMutex->unlock(); + deleteOrphaned(c); + senderMutex->lock(); + } else { + deleteOrphaned(c); + } + } } void QObjectPrivate::ConnectionData::deleteOrphaned(QObjectPrivate::ConnectionOrSignalVector *o) |