[PATCH xserver 1/2] Hold input lock for deviceProc

Peter Hutterer peter.hutterer at who-t.net
Fri Sep 9 02:33:12 UTC 2016


On Thu, Sep 08, 2016 at 11:02:30AM -0600, Keith Packard wrote:
> This ensures that the deviceProc is never called while the input
> thread is processing data from the device.
> 
> Signed-off-by: Keith Packard <keithp at keithp.com>
> ---
>  dix/devices.c | 22 +++++++++++++++++++---
>  1 file changed, 19 insertions(+), 3 deletions(-)
> 
> diff --git a/dix/devices.c b/dix/devices.c
> index 9de84a6..56aae85 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();

this one isn't needed, as a device that sends events before DEVICE_ON will
simply have all of them discarded anyway. but it won't hurt.

>      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();

same with this one, not needed but it won't hurt. 

Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>, thanks.

Cheers,
   Peter

> +
>      if (ret == Success && initialized) {
>          inputInfo.numDevices--;
>          SendDevicePresenceEvent(deviceid, DeviceRemoved);
> -- 
> 2.8.1
> 


More information about the xorg-devel mailing list