Fixed crash if there are multiple joysticks closed during the joystick update loop

This commit is contained in:
Sam Lantinga 2016-12-14 06:25:09 -08:00
parent f50a04009c
commit b4ea63ec2c
1 changed files with 12 additions and 15 deletions

View File

@ -34,7 +34,7 @@
static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE; static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE;
static SDL_Joystick *SDL_joysticks = NULL; 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 */ static SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */
void void
@ -458,7 +458,7 @@ SDL_JoystickClose(SDL_Joystick * joystick)
return; return;
} }
if (joystick == SDL_updating_joystick) { if (SDL_updating_joystick) {
SDL_UnlockJoystickList(); SDL_UnlockJoystickList();
return; return;
} }
@ -784,7 +784,7 @@ SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state)
void void
SDL_JoystickUpdate(void) SDL_JoystickUpdate(void)
{ {
SDL_Joystick *joystick, *joysticknext; SDL_Joystick *joystick;
SDL_LockJoystickList(); SDL_LockJoystickList();
@ -794,17 +794,12 @@ SDL_JoystickUpdate(void)
return; return;
} }
for (joystick = SDL_joysticks; joystick; joystick = joysticknext) { SDL_updating_joystick = SDL_TRUE;
/* 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; /* 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); SDL_SYS_JoystickUpdate(joystick);
if (joystick->force_recentering) { if (joystick->force_recentering) {
@ -825,12 +820,14 @@ SDL_JoystickUpdate(void)
joystick->force_recentering = SDL_FALSE; 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) { if (joystick->ref_count <= 0) {
SDL_JoystickClose(joystick); SDL_JoystickClose(joystick);
} }