summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qobject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qobject.cpp')
-rw-r--r--src/corelib/kernel/qobject.cpp19
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)