From 9050ce4ff569de97dbcdc837044d0cc3f7e01e6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 27 Jun 2018 16:59:57 +0200 Subject: [PATCH] macOS: Guard non-reentrant uses of NSOpenGLContext NSOpenGLContext should be re-entrant, but is not in practice, resulting in deadlocks when there are two render threads, eg: thread #23, name = 'QSGRenderThread' frame #0: 0x00007fff5c6dda4e libsystem_kernel.dylib`__psynch_mutexwait + 10 frame #1: 0x00007fff5c8a5b9d libsystem_pthread.dylib`_pthread_mutex_lock_wait + 83 frame #2: 0x00007fff5c8a34c8 libsystem_pthread.dylib`_pthread_mutex_lock_slow + 253 frame #3: 0x00007fff31ebb52e AppKit`flush_notify + 110 frame #4: 0x00007fff3e75ee2a GLEngine`glSwap_Exec + 186 frame #5: 0x00007fff3e740797 OpenGL`CGLFlushDrawable + 59 frame #6: 0x00007fff31ad43ac AppKit`-[NSOpenGLContext flushBuffer] + 27 ... Task-number: QTBUG-69040 Change-Id: I6f28b4cc5faf61ae93f66353ce2abdf8c223d994 Reviewed-by: Simon Hausmann --- src/plugins/platforms/cocoa/qcocoaglcontext.mm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index b656025ec7..7ffe0003d3 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -117,6 +117,9 @@ static void updateFormatFromContext(QSurfaceFormat *format) format->setProfile(QSurfaceFormat::CompatibilityProfile); } + // NSOpenGLContext is not re-entrant (https://openradar.appspot.com/37064579) +static QMutex s_contextMutex; + QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, const QVariant &nativeHandle) : m_context(nil), @@ -248,6 +251,7 @@ void QCocoaGLContext::swapBuffers(QPlatformSurface *surface) QWindow *window = static_cast(surface)->window(); setActiveWindow(window); + QMutexLocker locker(&s_contextMutex); [m_context flushBuffer]; } @@ -400,6 +404,7 @@ QFunctionPointer QCocoaGLContext::getProcAddress(const char *procName) void QCocoaGLContext::update() { + QMutexLocker locker(&s_contextMutex); [m_context update]; }