From 087aa1f3cb5975ef55e42db54487f737c93a4f0f Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 20 Nov 2014 11:08:13 +0100 Subject: 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 --- src/corelib/kernel/qeventdispatcher_win.cpp | 12 ++++++++++-- src/corelib/kernel/qeventdispatcher_win_p.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 62e6e9f051..1a8bb381aa 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -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(); } diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index a68f6cfa28..8022299a76 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -147,6 +147,7 @@ public: DWORD threadId; bool interrupt; + bool closingDown; // internal window handle used for socketnotifiers/timers/etc HWND internalHwnd; -- cgit v1.2.3