From 087aa1f3cb5975ef55e42db54487f737c93a4f0f Mon Sep 17 00:00:00 2001
From: Kai Koehne <kai.koehne@theqtcompany.com>
Date: Thu, 20 Nov 2014 11:08:13 +0100
Subject: [PATCH] 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>
---
 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 62e6e9f051f..1a8bb381aa9 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 a68f6cfa289..8022299a769 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;
-- 
GitLab