Fixed crash if there are multiple joysticks closed during the joystick update loop
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index 21e1365..4224570 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -34,7 +34,7 @@
static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE;
static SDL_Joystick *SDL_joysticks = NULL;
-static SDL_Joystick *SDL_updating_joystick = NULL;
+static SDL_bool SDL_updating_joystick = SDL_FALSE;
static SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */
void
@@ -458,7 +458,7 @@ SDL_JoystickClose(SDL_Joystick * joystick)
return;
}
- if (joystick == SDL_updating_joystick) {
+ if (SDL_updating_joystick) {
SDL_UnlockJoystickList();
return;
}
@@ -784,7 +784,7 @@ SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
void
SDL_JoystickUpdate(void)
{
- SDL_Joystick *joystick, *joysticknext;
+ SDL_Joystick *joystick;
SDL_LockJoystickList();
@@ -794,17 +794,12 @@ SDL_JoystickUpdate(void)
return;
}
- for (joystick = SDL_joysticks; joystick; joystick = joysticknext) {
- /* save off the next pointer, the Update call may cause a joystick removed event
- * and cause our joystick pointer to be freed
- */
- joysticknext = joystick->next;
-
- SDL_updating_joystick = joystick;
+ SDL_updating_joystick = SDL_TRUE;
- /* Make sure the list is unlocked while dispatching events to prevent application deadlocks */
- SDL_UnlockJoystickList();
+ /* Make sure the list is unlocked while dispatching events to prevent application deadlocks */
+ SDL_UnlockJoystickList();
+ for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
SDL_SYS_JoystickUpdate(joystick);
if (joystick->force_recentering) {
@@ -825,12 +820,14 @@ SDL_JoystickUpdate(void)
joystick->force_recentering = SDL_FALSE;
}
+ }
- SDL_LockJoystickList();
+ SDL_LockJoystickList();
- SDL_updating_joystick = NULL;
+ SDL_updating_joystick = SDL_FALSE;
- /* If the joystick was closed while updating, free it here */
+ /* If any joysticks were closed while updating, free them here */
+ for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
if (joystick->ref_count <= 0) {
SDL_JoystickClose(joystick);
}