Просмотр исходного кода

android: fixed a possible joystick-related deadlock on application termination

Sam Lantinga 15 часов назад
Родитель
Сommit
6b4ae68460
1 измененных файлов с 22 добавлено и 0 удалено
  1. 22 0
      src/video/android/SDL_androidevents.c

+ 22 - 0
src/video/android/SDL_androidevents.c

@@ -178,6 +178,26 @@ static void Android_OnDestroy(void)
 
 static void Android_HandleLifecycleEvent(SDL_AndroidLifecycleEvent event)
 {
+    // Make sure we're holding the joystick lock before dispatching life cycle events
+    // This prevents deadlocks of this form:
+    //   1. SDL locks the event watch list to dispatch the lifecycle event
+    //   2. a joystick sensor event arrives, taking the joystick lock
+    //   3. the lifecycle event dispatch calls into the application event
+    //      watcher, which closes joysticks, trying to take the joystick lock
+    //   4. SDL delivers the sensor event, trying lock the event watch list
+    //   5. BOOM, deadlock!
+    //
+    // There are a few solutions to this, most of which involve unlocking the
+    // event watch list while delivering events or unlocking the joystick lock
+    // while delivering joystick events, both of which reduce performance and
+    // are extremely risky, so we'll do this, which is the least risky option.
+    //
+    // If you end up needing to wait for another thread that handles joystick
+    // events in your life cycle handling, then you can simply unlock joysticks,
+    // wait for that thread to complete, and then re-lock joysticks.
+
+    SDL_LockJoysticks();
+
     switch (event) {
     case SDL_ANDROID_LIFECYCLE_WAKE:
         // Nothing to do, just return
@@ -197,6 +217,8 @@ static void Android_HandleLifecycleEvent(SDL_AndroidLifecycleEvent event)
     default:
         break;
     }
+
+    SDL_UnlockJoysticks();
 }
 
 static Sint64 GetLifecycleEventTimeout(bool paused, Sint64 timeoutNS)