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.
parent
02108cf7e5
commit
65fd633694
|
@ -128,6 +128,7 @@ FreeDevice(recDevice *removeDevice)
|
||||||
if (removeDevice) {
|
if (removeDevice) {
|
||||||
if (removeDevice->deviceRef) {
|
if (removeDevice->deviceRef) {
|
||||||
IOHIDDeviceUnscheduleFromRunLoop(removeDevice->deviceRef, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
|
IOHIDDeviceUnscheduleFromRunLoop(removeDevice->deviceRef, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
|
||||||
|
CFRelease(removeDevice->deviceRef);
|
||||||
removeDevice->deviceRef = NULL;
|
removeDevice->deviceRef = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +207,11 @@ JoystickDeviceWasRemovedCallback(void *ctx, IOReturn result, void *sender)
|
||||||
{
|
{
|
||||||
recDevice *device = (recDevice *) ctx;
|
recDevice *device = (recDevice *) ctx;
|
||||||
device->removed = SDL_TRUE;
|
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) {
|
if (device->ffeffect_ref) {
|
||||||
FFDeviceReleaseEffect(device->ffdevice, device->ffeffect_ref);
|
FFDeviceReleaseEffect(device->ffdevice, device->ffeffect_ref);
|
||||||
device->ffeffect_ref = NULL;
|
device->ffeffect_ref = NULL;
|
||||||
|
@ -428,6 +433,15 @@ GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
|
||||||
return SDL_FALSE; /* Filter device list to non-keyboard/mouse stuff */
|
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;
|
pDevice->deviceRef = hidDevice;
|
||||||
|
|
||||||
refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDVendorIDKey));
|
refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDVendorIDKey));
|
||||||
|
@ -546,12 +560,12 @@ JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDevic
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetDeviceInfo(ioHIDDeviceObject, device)) {
|
if (!GetDeviceInfo(ioHIDDeviceObject, device)) {
|
||||||
SDL_free(device);
|
FreeDevice(device);
|
||||||
return; /* not a device we care about, probably. */
|
return; /* not a device we care about, probably. */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_ShouldIgnoreJoystick(device->product, device->guid)) {
|
if (SDL_ShouldIgnoreJoystick(device->product, device->guid)) {
|
||||||
SDL_free(device);
|
FreeDevice(device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue