From 09504d484c258eafb10ac12eeda1becda5b985c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 10 May 2019 16:06:47 +0200 Subject: [PATCH] macOS: Guard against display on non-main threads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AppKit will in some cases ask our view to display on secondary threads if we call APIs that are only supposed to be called on the main thread, such as -[NSOpenGLContext setView:] or -[NSOpenGLContext update]. Forwarding this display-request is bad, as QtGui expects all window system events to come on the main thread, and we can easily deadlock client code such as the Qt Quick threaded renderer. Change-Id: I1daeabf1dca6ca8ba908d3998b444a2089681e3a Reviewed-by: Morten Johan Sørvig Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qnsview_drawing.mm | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/plugins/platforms/cocoa/qnsview_drawing.mm b/src/plugins/platforms/cocoa/qnsview_drawing.mm index 3690d6ebb4..116a9a73df 100644 --- a/src/plugins/platforms/cocoa/qnsview_drawing.mm +++ b/src/plugins/platforms/cocoa/qnsview_drawing.mm @@ -189,6 +189,15 @@ - (void)displayLayer:(CALayer *)layer { + if (!NSThread.isMainThread) { + // Qt is calling AppKit APIs such as -[NSOpenGLContext setView:] on secondary threads, + // which we shouldn't do. This may result in AppKit (wrongly) triggering a display on + // the thread where we made the call, so block it here and defer to the main thread. + qCWarning(lcQpaDrawing) << "Display non non-main thread! Deferring to main thread"; + dispatch_async(dispatch_get_main_queue(), ^{ self.needsDisplay = YES; }); + return; + } + Q_ASSERT(layer == self.layer); if (!m_platformWindow)