Commit 1fb20f0ab9f1b1ad51a79dbf59c50db5cc91d6f9

Ryan C. Gordon 2018-10-18T23:38:27

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.

diff --git a/src/video/cocoa/SDL_cocoaopengl.m b/src/video/cocoa/SDL_cocoaopengl.m
index c7d0c60..9539c17 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 05bbd34..b1c26fa 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 9770224..20bdfa7 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 */