summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@trolltech.com>2010-03-01 14:21:14 (GMT)
committerOlivier Goffart <ogoffart@trolltech.com>2010-03-01 14:36:35 (GMT)
commit65f993d679140fb2dc29b48c9d9d8d2fc5af893d (patch)
tree1ca33fb0fb96267e54d292b13302ce0a46764afb
parentd04f5336f769d9e5d2f9105e1da4a7d23ea91795 (diff)
downloadQt-65f993d679140fb2dc29b48c9d9d8d2fc5af893d.zip
Qt-65f993d679140fb2dc29b48c9d9d8d2fc5af893d.tar.gz
Qt-65f993d679140fb2dc29b48c9d9d8d2fc5af893d.tar.bz2
QObject: fix crash when deleteing the receiver object withing a DirectConncetion involving two threads.
We did not set the sender(), but we tried to reset it anyway. Task-number: QTBUG-7935 Reviewed-by: Brad
-rw-r--r--src/corelib/kernel/qobject.cpp17
-rw-r--r--tests/auto/qobject/tst_qobject.cpp20
2 files changed, 30 insertions, 7 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 5298fff..689e44c 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -3264,12 +3264,14 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign
const int method = c->method;
QObjectPrivate::Sender currentSender;
- currentSender.sender = sender;
- currentSender.signal = signal_absolute_index;
- currentSender.ref = 1;
+ const bool receiverInSameThread = currentThreadData == receiver->d_func()->threadData;
QObjectPrivate::Sender *previousSender = 0;
- if (currentThreadData == receiver->d_func()->threadData)
+ if (receiverInSameThread) {
+ currentSender.sender = sender;
+ currentSender.signal = signal_absolute_index;
+ currentSender.ref = 1;
previousSender = QObjectPrivate::setCurrentSender(receiver, &currentSender);
+ }
locker.unlock();
if (qt_signal_spy_callback_set.slot_begin_callback != 0) {
@@ -3285,8 +3287,8 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign
metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
} QT_CATCH(...) {
locker.relock();
-
- QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
+ if (receiverInSameThread)
+ QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
--connectionLists->inUse;
Q_ASSERT(connectionLists->inUse >= 0);
@@ -3301,7 +3303,8 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign
locker.relock();
- QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
+ if (receiverInSameThread)
+ QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
if (connectionLists->orphaned)
break;
diff --git a/tests/auto/qobject/tst_qobject.cpp b/tests/auto/qobject/tst_qobject.cpp
index 4fa6aaa..985dfa4 100644
--- a/tests/auto/qobject/tst_qobject.cpp
+++ b/tests/auto/qobject/tst_qobject.cpp
@@ -2647,6 +2647,16 @@ void tst_QObject::installEventFilter()
QVERIFY(spy.eventList().isEmpty());
}
+class EmitThread : public QThread
+{ Q_OBJECT
+public:
+ void run(void) {
+ emit work();
+ }
+signals:
+ void work();
+};
+
class DeleteObject : public QObject
{
Q_OBJECT
@@ -2712,6 +2722,16 @@ void tst_QObject::deleteSelfInSlot()
QVERIFY(thread.wait(10000));
}
+
+ {
+ EmitThread sender;
+ DeleteObject *receiver = new DeleteObject();
+ connect(&sender, SIGNAL(work()), receiver, SLOT(deleteSelf()), Qt::DirectConnection);
+ QPointer<DeleteObject> p = receiver;
+ sender.start();
+ QVERIFY(sender.wait(10000));
+ QVERIFY(p.isNull());
+ }
}
class DisconnectObject : public QObject