فهرست منبع

Reduce the chance of destroying the joystick mutex while it's in use

Fixes https://github.com/libsdl-org/SDL/issues/7811
Sam Lantinga 1 سال پیش
والد
کامیت
cdc40ee054
1فایلهای تغییر یافته به همراه17 افزوده شده و 4 حذف شده
  1. 17 4
      src/joystick/SDL_joystick.c

+ 17 - 4
src/joystick/SDL_joystick.c

@@ -109,6 +109,7 @@ static SDL_JoystickDriver *SDL_joystick_drivers[] = {
 static
 #endif
 SDL_Mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */
+static SDL_AtomicInt SDL_joystick_lock_pending;
 static int SDL_joysticks_locked;
 static SDL_bool SDL_joysticks_initialized;
 static SDL_bool SDL_joysticks_quitting = SDL_FALSE;
@@ -138,23 +139,35 @@ SDL_bool SDL_JoysticksQuitting(void)
 
 void SDL_LockJoysticks(void)
 {
+    SDL_AtomicIncRef(&SDL_joystick_lock_pending);
     SDL_LockMutex(SDL_joystick_lock);
+    SDL_AtomicDecRef(&SDL_joystick_lock_pending);
 
     ++SDL_joysticks_locked;
 }
 
 void SDL_UnlockJoysticks(void)
 {
+    SDL_Mutex *joystick_lock = SDL_joystick_lock;
+    SDL_bool last_unlock = SDL_FALSE;
+
     --SDL_joysticks_locked;
 
-    SDL_UnlockMutex(SDL_joystick_lock);
+    if (!SDL_joysticks_initialized) {
+        if (!SDL_joysticks_locked && SDL_AtomicGet(&SDL_joystick_lock_pending) == 0) {
+            /* NOTE: There's a small window here where another thread could lock the mutex */
+            SDL_joystick_lock = NULL;
+            last_unlock = SDL_TRUE;
+        }
+    }
+
+    SDL_UnlockMutex(joystick_lock);
 
     /* The last unlock after joysticks are uninitialized will cleanup the mutex,
      * allowing applications to lock joysticks while reinitializing the system.
      */
-    if (SDL_joystick_lock && !SDL_joysticks_locked && !SDL_joysticks_initialized) {
-        SDL_DestroyMutex(SDL_joystick_lock);
-        SDL_joystick_lock = NULL;
+    if (last_unlock) {
+        SDL_DestroyMutex(joystick_lock);
     }
 }