Fix for Bug 5034 - Replugging in a controller crashes on macOS in SDL 2.0.12
This is a multi-part fix, and is the 2nd attempt at a fix for Bug 5034. Here are the problems being addressed: 1. On macOS 10.14.x and earlier, trying to call IOHIDDeviceUnscheduleFromRunLoop without a prior, paired call to IOHIDDeviceScheduleWithRunLoop, appears to lead to a crash. A per-device flag has been added to make sure that these calls are paired. 2. DARWIN_JoystickDetect was free'ing its SDL_joystick's hwdata field (via FreeDevice) without setting it to NULL, and DARWIN_JoystickRumble wasn't checking for a NULL hwdata. FreeDevice will now set hwdata to NULL and DARWIN_JoystickRumble will check for a NULL hwdata.
parent
4c22a21e06
commit
7e5340c5ac
|
@ -127,11 +127,28 @@ FreeDevice(recDevice *removeDevice)
|
|||
recDevice *pDeviceNext = NULL;
|
||||
if (removeDevice) {
|
||||
if (removeDevice->deviceRef) {
|
||||
IOHIDDeviceUnscheduleFromRunLoop(removeDevice->deviceRef, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
|
||||
if (removeDevice->runLoopAttached) {
|
||||
/* Calling IOHIDDeviceUnscheduleFromRunLoop without a prior,
|
||||
* paired call to IOHIDDeviceScheduleWithRunLoop can lead
|
||||
* to crashes in MacOS 10.14.x and earlier. This doesn't
|
||||
* appear to be a problem in MacOS 10.15.x, but we'll
|
||||
* do it anyways. (Part-of fix for Bug 5034)
|
||||
*/
|
||||
IOHIDDeviceUnscheduleFromRunLoop(removeDevice->deviceRef, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
|
||||
}
|
||||
CFRelease(removeDevice->deviceRef);
|
||||
removeDevice->deviceRef = NULL;
|
||||
}
|
||||
|
||||
/* clear out any reference to removeDevice from an associated,
|
||||
* live instance of SDL_Joystick (Part-of fix for Bug 5034)
|
||||
*/
|
||||
SDL_LockJoysticks();
|
||||
if (removeDevice->joystick) {
|
||||
removeDevice->joystick->hwdata = NULL;
|
||||
}
|
||||
SDL_UnlockJoysticks();
|
||||
|
||||
/* save next device prior to disposing of this device */
|
||||
pDeviceNext = removeDevice->pNext;
|
||||
|
||||
|
@ -398,6 +415,7 @@ AddHIDElement(const void *value, void *parameter)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static SDL_bool
|
||||
GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
|
||||
{
|
||||
|
@ -552,6 +570,7 @@ JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDevic
|
|||
/* Get notified when this device is disconnected. */
|
||||
IOHIDDeviceRegisterRemovalCallback(ioHIDDeviceObject, JoystickDeviceWasRemovedCallback, device);
|
||||
IOHIDDeviceScheduleWithRunLoop(ioHIDDeviceObject, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE);
|
||||
device->runLoopAttached = SDL_TRUE;
|
||||
|
||||
/* Allocate an instance ID for this device */
|
||||
device->instance_id = SDL_GetNextJoystickInstanceID();
|
||||
|
@ -760,6 +779,7 @@ DARWIN_JoystickOpen(SDL_Joystick * joystick, int device_index)
|
|||
|
||||
joystick->instance_id = device->instance_id;
|
||||
joystick->hwdata = device;
|
||||
device->joystick = joystick;
|
||||
joystick->name = device->product;
|
||||
|
||||
joystick->naxes = device->axes;
|
||||
|
@ -870,6 +890,10 @@ DARWIN_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint
|
|||
|
||||
/* Scale and average the two rumble strengths */
|
||||
Sint16 magnitude = (Sint16)(((low_frequency_rumble / 2) + (high_frequency_rumble / 2)) / 2);
|
||||
|
||||
if (!device) {
|
||||
return SDL_SetError("Rumble failed, device disconnected");
|
||||
}
|
||||
|
||||
if (!device->ffservice) {
|
||||
return SDL_Unsupported();
|
||||
|
@ -1007,6 +1031,10 @@ DARWIN_JoystickUpdate(SDL_Joystick * joystick)
|
|||
static void
|
||||
DARWIN_JoystickClose(SDL_Joystick * joystick)
|
||||
{
|
||||
recDevice *device = joystick->hwdata;
|
||||
if (device) {
|
||||
device->joystick = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -66,6 +66,8 @@ struct joystick_hwdata
|
|||
recElement *firstHat;
|
||||
|
||||
SDL_bool removed;
|
||||
SDL_Joystick *joystick;
|
||||
SDL_bool runLoopAttached; /* is 'deviceRef' attached to a CFRunLoop? */
|
||||
|
||||
int instance_id;
|
||||
SDL_JoystickGUID guid;
|
||||
|
|
Loading…
Reference in New Issue