From c4886ca42732feb51648985b741a8113382a6fba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?=
 <morten.sorvig@theqtcompany.com>
Date: Mon, 14 Mar 2016 09:52:09 +0100
Subject: [PATCH] Cocoa: Fix crash on screen disconnect.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Maintain virtual siblings list on screen deletion.

QCocoaIntegration::updateScreens() has a loop which
will delete all non-current QScreen objects using
QPlatformIntegration::destroyScreen().

destroyScreen() vill eventually call QWindowPrivate::
setTopLevelScreen() which accesses the virtual siblings
list for the deleted screen.

This can cause a stale pointer access if the virtual
screen list is not up to date, especially when disconnecting
two screens at the same time.

Change-Id: Ia6b9d01edf8e5eea25b64604a2b3b28b173125f7
Task-number: QTBUG-48275
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@theqtcompany.com>
Reviewed-by: Morten Johan Sørvig <morten.sorvig@theqtcompany.com>
---
 src/plugins/platforms/cocoa/qcocoaintegration.mm | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 6bec6b191d5..91d4b2706bc 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -422,14 +422,18 @@ void QCocoaIntegration::updateScreens()
         }
         siblings << screen;
     }
+
+    // Set virtual siblings list. All screens in mScreens are siblings, because we ignored the
+    // mirrors. Note that some of the screens we update the siblings list for here may be deleted
+    // below, but update anyway to keep the to-be-deleted screens out of the siblings list.
+    foreach (QCocoaScreen* screen, mScreens)
+        screen->setVirtualSiblings(siblings);
+
     // Now the leftovers in remainingScreens are no longer current, so we can delete them.
     foreach (QCocoaScreen* screen, remainingScreens) {
         mScreens.removeOne(screen);
         destroyScreen(screen);
     }
-    // All screens in mScreens are siblings, because we ignored the mirrors.
-    foreach (QCocoaScreen* screen, mScreens)
-        screen->setVirtualSiblings(siblings);
 }
 
 QCocoaScreen *QCocoaIntegration::screenAtIndex(int index)
-- 
GitLab