diff options
author | Keith Packard <keithp@keithp.com> | 2016-09-08 11:02:30 -0600 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2016-09-15 07:50:38 +1000 |
commit | 52d6a1e832a5e62289dd4f32824ae16a78dfd7e8 (patch) | |
tree | b29191f9992e1018f0e271c2d40e9f7092c1db3a /dix | |
parent | dfc91f0f630f9e0500fc28b18e3f2851024d719f (diff) |
Hold input lock for deviceProc
This ensures that the deviceProc is never called while the input
thread is processing data from the device.
Signed-off-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'dix')
-rw-r--r-- | dix/devices.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/dix/devices.c b/dix/devices.c index 9de84a627..56aae85e0 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -399,9 +399,11 @@ EnableDevice(DeviceIntPtr dev, BOOL sendevent) } } + input_lock(); if ((*prev != dev) || !dev->inited || ((ret = (*dev->deviceProc) (dev, DEVICE_ON)) != Success)) { ErrorF("[dix] couldn't enable device %d\n", dev->id); + input_unlock(); return FALSE; } dev->enabled = TRUE; @@ -410,6 +412,7 @@ EnableDevice(DeviceIntPtr dev, BOOL sendevent) for (prev = &inputInfo.devices; *prev; prev = &(*prev)->next); *prev = dev; dev->next = NULL; + input_unlock(); enabled = TRUE; XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED), @@ -488,20 +491,20 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent) if (dev->spriteInfo->paired) dev->spriteInfo->paired = NULL; + input_lock(); (void) (*dev->deviceProc) (dev, DEVICE_OFF); dev->enabled = FALSE; - FreeSprite(dev); - /* now that the device is disabled, we can reset the event reader's * last.slave */ - input_lock(); for (other = inputInfo.devices; other; other = other->next) { if (other->last.slave == dev) other->last.slave = NULL; } input_unlock(); + FreeSprite(dev); + LeaveWindow(dev); SetFocusOut(dev); @@ -569,7 +572,9 @@ ActivateDevice(DeviceIntPtr dev, BOOL sendevent) if (!dev || !dev->deviceProc) return BadImplementation; + input_lock(); ret = (*dev->deviceProc) (dev, DEVICE_INIT); + input_unlock(); dev->inited = (ret == Success); if (!dev->inited) return ret; @@ -935,6 +940,8 @@ FreeAllDeviceClasses(ClassesPtr classes) * enable it again and free associated structs. If you want the device to just * be disabled, DisableDevice(). * Don't call this function directly, use RemoveDevice() instead. + * + * Called with input lock held. */ static void CloseDevice(DeviceIntPtr dev) @@ -1071,6 +1078,11 @@ void AbortDevices(void) { DeviceIntPtr dev; + + /* Do not call input_lock as we don't know what + * state the input thread might be in, and that could + * cause a dead-lock. + */ nt_list_for_each_entry(dev, inputInfo.devices, next) { if (!IsMaster(dev)) (*dev->deviceProc) (dev, DEVICE_ABORT); @@ -1135,6 +1147,8 @@ RemoveDevice(DeviceIntPtr dev, BOOL sendevent) flags[dev->id] = XIDeviceDisabled; } + input_lock(); + prev = NULL; for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) { next = tmp->next; @@ -1167,6 +1181,8 @@ RemoveDevice(DeviceIntPtr dev, BOOL sendevent) } } + input_unlock(); + if (ret == Success && initialized) { inputInfo.numDevices--; SendDevicePresenceEvent(deviceid, DeviceRemoved); |