summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2013-11-21 15:22:53 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-22 07:48:08 +0100
commit3f97e3844064fb3ecf8881067cec095df25c9782 (patch)
tree8057fadb6b968d776865d82daeed36d1d3a56a41 /src
parentbb090fa76e352a253805749894f4ee1676481f9d (diff)
Fix race condition between destruction of QObjects
If the two QObjecs are connected and destroyed at the same time, it is possible to hit a case where QObject::metaObject and QObject::disconnectNotify is called on a destroyed object. This patch moves the calls up before the removal of the connection. This ensure the sender object will have to block on the receivers connection mutex and can not finish destruction before disconnectNotify is called. Task-number: QTBUG-34131 Change-Id: I398116fe7bc6a195991aff9961d89a8b0ac8d53c Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/kernel/qobject.cpp7
1 files changed, 4 insertions, 3 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index c19c3fcbb5..282672ddc7 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -868,6 +868,10 @@ QObject::~QObject()
QObjectPrivate::Connection *node = d->senders;
while (node) {
QObject *sender = node->sender;
+ // Send disconnectNotify before removing the connection from sender's connection list.
+ // This ensures any eventual destructor of sender will block on getting receiver's lock
+ // and not finish until we release it.
+ sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), node->signal_index));
QMutex *m = signalSlotLock(sender);
node->prev = &node;
bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
@@ -881,8 +885,6 @@ QObject::~QObject()
if (senderLists)
senderLists->dirty = true;
- int signal_index = node->signal_index;
-
QtPrivate::QSlotObjectBase *slotObj = Q_NULLPTR;
if (node->isSlotObject) {
slotObj = node->slotObj;
@@ -899,7 +901,6 @@ QObject::~QObject()
locker.relock();
}
- sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), signal_index));
}
}