Windows: Prevent registration of timers in shutdown phase

Do not register new timers after closingDown() has been called. They
might call back into QEventDispatcherWin32 after the object has been
destructed, leading to crashes on exit.

registerSocketNotifier has a similar protection using
QCoreApplication::closingDown(). This however does not work in all cases,
because QEventDispatcher::closingDown() is called in
~QGuiApplication(), while QCoreApplication::is_app_closing is set
in ~QCoreApplication(). In between qt_call_post_routines() is called,
which might trigger new timers to be registered.

Task-number: QTBUG-42772
Change-Id: I91325fb10e38c117c1cbedfee272d0ab6a5ca8fa
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
This commit is contained in:
Kai Koehne 2014-11-20 11:08:13 +01:00 committed by Jani Heikkinen
parent 52f5bf9cd5
commit 087aa1f3cb
2 changed files with 11 additions and 2 deletions

View File

@ -307,8 +307,9 @@ static void resolveTimerAPI()
}
QEventDispatcherWin32Private::QEventDispatcherWin32Private()
: threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0), getMessageHook(0),
serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0), wakeUps(0)
: threadId(GetCurrentThreadId()), interrupt(false), closingDown(false), internalHwnd(0),
getMessageHook(0), serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0),
wakeUps(0)
{
resolveTimerAPI();
}
@ -931,6 +932,11 @@ void QEventDispatcherWin32::registerTimer(int timerId, int interval, Qt::TimerTy
Q_D(QEventDispatcherWin32);
// exiting ... do not register new timers
// (QCoreApplication::closingDown() is set too late to be used here)
if (d->closingDown)
return;
WinTimerInfo *t = new WinTimerInfo;
t->dispatcher = this;
t->timerId = timerId;
@ -1155,6 +1161,8 @@ void QEventDispatcherWin32::closingDown()
d->timerVec.clear();
d->timerDict.clear();
d->closingDown = true;
uninstallMessageHook();
}

View File

@ -147,6 +147,7 @@ public:
DWORD threadId;
bool interrupt;
bool closingDown;
// internal window handle used for socketnotifiers/timers/etc
HWND internalHwnd;