summaryrefslogtreecommitdiff
path: root/dix
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2016-09-08 11:02:30 -0600
committerPeter Hutterer <peter.hutterer@who-t.net>2016-09-15 07:50:38 +1000
commit52d6a1e832a5e62289dd4f32824ae16a78dfd7e8 (patch)
treeb29191f9992e1018f0e271c2d40e9f7092c1db3a /dix
parentdfc91f0f630f9e0500fc28b18e3f2851024d719f (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.c22
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);