diff options
author | Olivier Goffart <ogoffart@trolltech.com> | 2010-03-01 14:21:14 (GMT) |
---|---|---|
committer | Olivier Goffart <ogoffart@trolltech.com> | 2010-03-01 14:36:35 (GMT) |
commit | 65f993d679140fb2dc29b48c9d9d8d2fc5af893d (patch) | |
tree | 1ca33fb0fb96267e54d292b13302ce0a46764afb | |
parent | d04f5336f769d9e5d2f9105e1da4a7d23ea91795 (diff) | |
download | Qt-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.cpp | 17 | ||||
-rw-r--r-- | tests/auto/qobject/tst_qobject.cpp | 20 |
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, ¤tSender); + } 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, ¤tSender, previousSender); + if (receiverInSameThread) + QObjectPrivate::resetCurrentSender(receiver, ¤tSender, 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, ¤tSender, previousSender); + if (receiverInSameThread) + QObjectPrivate::resetCurrentSender(receiver, ¤tSender, 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 |