Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
FIX for SDL-4927: CFRetain+CFRelease a game controller's IOKit object
This fixes a crash whereby SDL could crash on macOS/Darwin, if and when a
USB game controller gets unplugged.  SDL was not retaining a reference
to the controller's OS/IOKit-provided 'device object', and was capable
of trying to use it, after a device was hot-unplugged.
  • Loading branch information
DavidLudwig committed Jan 30, 2020
1 parent 02108cf commit 65fd633
Showing 1 changed file with 17 additions and 3 deletions.
20 changes: 17 additions & 3 deletions src/joystick/darwin/SDL_sysjoystick.c
Expand Up @@ -128,6 +128,7 @@ FreeDevice(recDevice *removeDevice)
if (removeDevice) {
if (removeDevice->deviceRef) {
IOHIDDeviceUnscheduleFromRunLoop(removeDevice->deviceRef, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
CFRelease(removeDevice->deviceRef);
removeDevice->deviceRef = NULL;
}

Expand Down Expand Up @@ -206,7 +207,11 @@ JoystickDeviceWasRemovedCallback(void *ctx, IOReturn result, void *sender)
{
recDevice *device = (recDevice *) ctx;
device->removed = SDL_TRUE;
device->deviceRef = NULL; // deviceRef was invalidated due to the remove
if (device->deviceRef) {
// deviceRef was invalidated due to the remove
CFRelease(device->deviceRef);
device->deviceRef = NULL;
}
if (device->ffeffect_ref) {
FFDeviceReleaseEffect(device->ffdevice, device->ffeffect_ref);
device->ffeffect_ref = NULL;
Expand Down Expand Up @@ -428,6 +433,15 @@ GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
return SDL_FALSE; /* Filter device list to non-keyboard/mouse stuff */
}

/* Make sure we retain the use of the IOKit-provided device-object,
lest the device get disconnected and we try to use it. (Fixes
SDL-Bugzilla #4961, aka. https://bugzilla.libsdl.org/show_bug.cgi?id=4961 )
*/
CFRetain(hidDevice);

/* Now that we've CFRetain'ed the device-object (for our use), we'll
save the reference to it.
*/
pDevice->deviceRef = hidDevice;

refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDVendorIDKey));
Expand Down Expand Up @@ -546,12 +560,12 @@ JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDevic
}

if (!GetDeviceInfo(ioHIDDeviceObject, device)) {
SDL_free(device);
FreeDevice(device);
return; /* not a device we care about, probably. */
}

if (SDL_ShouldIgnoreJoystick(device->product, device->guid)) {
SDL_free(device);
FreeDevice(device);
return;
}

Expand Down

0 comments on commit 65fd633

Please sign in to comment.