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
parent
e07bdb8f74
commit
d6d9edd7c4
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue