Fix dead lock in the Qt event handling

The deadlock is caused because the QEvent is destroyed while holding the
event list mutex. And the QEvent may have a custom destructor that will
re-enter the event handlng code.

The QScopedPointer that should destroy the event must be created after
the MutexUnlocker.

Regression introduced by commit f9035587b9

Task-number: QTBUG-31606
Change-Id: I6b2cbc2656eacdec61b641886953f00bf5b3ff36
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Olivier Goffart 2013-07-09 15:31:26 +02:00 committed by The Qt Project
parent e07bdb8f74
commit d6d9edd7c4
2 changed files with 32 additions and 2 deletions

View File

@ -1451,7 +1451,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
// first, we diddle the event so that we can deliver
// it, and that no one will try to touch it later.
pe.event->posted = false;
QScopedPointer<QEvent> e(pe.event);
QEvent *e = pe.event;
QObject * r = pe.receiver;
--r->d_func()->postedEvents;
@ -1469,8 +1469,10 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
};
MutexUnlocker unlocker(locker);
QScopedPointer<QEvent> event_deleter(e); // will delete the event (with the mutex unlocked)
// after all that work, it's time to deliver the event.
QCoreApplication::sendEvent(r, e.data());
QCoreApplication::sendEvent(r, e);
// careful when adding anything below this point - the
// sendEvent() call might invalidate any invariants this

View File

@ -69,6 +69,7 @@ private slots:
void eventLoopExecAfterExit();
void customEventDispatcher();
void testQuitLock();
void QTBUG31606_QEventDestructorDeadLock();
};
class EventSpy : public QObject
@ -769,6 +770,33 @@ void tst_QCoreApplication::testQuitLock()
app.exec();
}
void tst_QCoreApplication::QTBUG31606_QEventDestructorDeadLock()
{
class MyEvent : public QEvent
{ public:
MyEvent() : QEvent(QEvent::Type(QEvent::User + 1)) {}
~MyEvent() {
QCoreApplication::postEvent(qApp, new QEvent(QEvent::Type(QEvent::User+2)));
}
};
int argc = 1;
char *argv[] = { const_cast<char*>("tst_qcoreapplication") };
QCoreApplication app(argc, argv);
EventSpy spy;
app.installEventFilter(&spy);
QCoreApplication::postEvent(&app, new MyEvent);
QCoreApplication::processEvents();
QVERIFY(spy.recordedEvents.contains(QEvent::User + 1));
QVERIFY(!spy.recordedEvents.contains(QEvent::User + 2));
QCoreApplication::processEvents();
QVERIFY(spy.recordedEvents.contains(QEvent::User + 2));
}
static void createQObjectOnDestruction()
{
// Make sure that we can create a QObject after the last QObject has been