From 1fb20f0ab9f1b1ad51a79dbf59c50db5cc91d6f9 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 18 Oct 2018 23:38:27 -0400 Subject: [PATCH] cocoa: Put a mutex around GL_SwapBuffers. Prevents deadlock when swapping two different GL contexts on two different threads at the same time on macOS 10.14 ("Mojave"). Fixes Bugzilla #4278. --- src/video/cocoa/SDL_cocoaopengl.m | 6 ++++++ src/video/cocoa/SDL_cocoavideo.h | 2 +- src/video/cocoa/SDL_cocoavideo.m | 8 ++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/video/cocoa/SDL_cocoaopengl.m b/src/video/cocoa/SDL_cocoaopengl.m index c7d0c60e5..9539c1779 100644 --- a/src/video/cocoa/SDL_cocoaopengl.m +++ b/src/video/cocoa/SDL_cocoaopengl.m @@ -410,8 +410,14 @@ Cocoa_GL_SwapWindow(_THIS, SDL_Window * window) { @autoreleasepool { SDLOpenGLContext* nscontext = (SDLOpenGLContext*)SDL_GL_GetCurrentContext(); + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; + + /* on 10.14 ("Mojave") and later, this deadlocks if two contexts in two + threads try to swap at the same time, so put a mutex around it. */ + SDL_LockMutex(videodata->swaplock); [nscontext flushBuffer]; [nscontext updateIfNeeded]; + SDL_UnlockMutex(videodata->swaplock); return 0; }} diff --git a/src/video/cocoa/SDL_cocoavideo.h b/src/video/cocoa/SDL_cocoavideo.h index 05bbd3483..b1c26fa7e 100644 --- a/src/video/cocoa/SDL_cocoavideo.h +++ b/src/video/cocoa/SDL_cocoavideo.h @@ -107,7 +107,7 @@ typedef struct SDL_VideoData Uint32 screensaver_activity; BOOL screensaver_use_iopm; IOPMAssertionID screensaver_assertion; - + SDL_mutex *swaplock; } SDL_VideoData; /* Utility functions */ diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m index 977022494..20bdfa791 100644 --- a/src/video/cocoa/SDL_cocoavideo.m +++ b/src/video/cocoa/SDL_cocoavideo.m @@ -175,15 +175,23 @@ Cocoa_VideoInit(_THIS) /* The IOPM assertion API can disable the screensaver as of 10.7. */ data->screensaver_use_iopm = floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6; + data->swaplock = SDL_CreateMutex(); + if (!data->swaplock) { + return -1; + } + return 0; } void Cocoa_VideoQuit(_THIS) { + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; Cocoa_QuitModes(_this); Cocoa_QuitKeyboard(_this); Cocoa_QuitMouse(_this); + SDL_DestroyMutex(data->swaplock); + data->swaplock = NULL; } /* This function assumes that it's called from within an autorelease pool */