[PATCH xf86-input-libinput] Replace the "fd" option when enabling dependent devices

Hans de Goede hdegoede at redhat.com
Fri Nov 20 01:12:27 PST 2015


Hi,

On 20-11-15 03:29, Peter Hutterer wrote:
> The server uses pInfo->major/minor to detect if another device is using the
> same path for a logind-controlled fd. If so, it reuses that device's
> pInfo->fd and sets the "fd" option to that value.
>
> That pInfo->fd is the libinput epollfd though, not the actual device fd.
>
> This doesn't matter for us, since we manage the fds largely ourselves and the
> pInfo->fd we use is the epollfd anyway. On unplug however, the udev code
> triggers a device removal for all devices, including the duplicated ones. When
> we disable device, we restore the pInfo->fd from the "fd" option so that the
> server can request logind to close the fd.
>
> That only works if the "fd" option is correct, otherwise the server asks
> logind to close the epollfd and everyone is unhappy.
>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
> I had to revert the patch shortly after pushing because it caused hangs in a
> logind setup on device unplug. This is on top of the original bug since it's
> a bit convoluted and a lot easier to understand when it's not squashed in.
> For the actual final patch, I'll squash them together though.
>
> Not happy with this approach, but short of a big rewrite of the server's
> input APIs there isn't that much we can do. And no-one is keen to do that
> atm :)

FWIW I cannot think of a better fix either.

It took me a while to wrap my head around this patch, but after that I
cannot find anything wrong with it:

Reviewed-by: Hans de Goede <hdegoede at redhat.com>

Regards,

Hans



>   src/xf86libinput.c | 37 ++++++++++++++++++++++++++++++++++---
>   1 file changed, 34 insertions(+), 3 deletions(-)
>
> diff --git a/src/xf86libinput.c b/src/xf86libinput.c
> index 430fc9a..ee2165a 100644
> --- a/src/xf86libinput.c
> +++ b/src/xf86libinput.c
> @@ -83,6 +83,7 @@ struct xf86libinput_device {
>   	uint32_t id;
>   	struct libinput_device *device;
>   	struct xorg_list device_list;
> +	int server_fd;
>   };
>
>   struct xf86libinput {
> @@ -236,15 +237,40 @@ xf86libinput_shared_unref(struct xf86libinput_device *shared_device)
>   }
>
>   static inline struct libinput_device *
> -xf86libinput_shared_enable(struct xf86libinput_device *shared_device,
> +xf86libinput_shared_enable(InputInfoPtr pInfo,
> +			   struct xf86libinput_device *shared_device,
>   			   const char *path)
>   {
>   	struct libinput_device *device;
>   	struct libinput *libinput = driver_context.libinput;
>
> +	/* With systemd-logind the server requests the fd from logind, sets
> +	 * pInfo->fd and sets the "fd" option to the fd number.
> +	 *
> +	 * If we have a second device that uses the same path, the server
> +	 * checks all pInfo->major/minor for a match and returns the matched
> +	 * device's pInfo->fd. In this driver, this fd is the epollfd, not
> +	 * the actual device. This causes troubles when removing the
> +	 * device.
> +	 *
> +	 * What we need to do here is: after enabling the device the first
> +	 * time extract the real fd and store it in the shared device
> +	 * struct. The second device replaces the pInfo->options "fd" with
> +	 * the real fd we're using.
> +	 *
> +	 * When the device is unplugged, the server now correctly finds two
> +	 * devices on the real fd and releases them in order.
> +	 */
>   	shared_device->enabled_count++;
> -	if (shared_device->enabled_count > 1)
> +	if (shared_device->enabled_count > 1) {
> +		if (pInfo->flags & XI86_SERVER_FD) {
> +			pInfo->options = xf86ReplaceIntOption(pInfo->options,
> +							      "fd",
> +							      shared_device->server_fd);
> +		}
> +
>   		return shared_device->device;
> +	}
>
>   	device = libinput_path_add_device(libinput, path);
>   	if (!device)
> @@ -253,6 +279,10 @@ xf86libinput_shared_enable(struct xf86libinput_device *shared_device,
>   	libinput_device_set_user_data(device, shared_device);
>   	shared_device->device = libinput_device_ref(device);
>
> +	if (pInfo->flags & XI86_SERVER_FD)
> +		shared_device->server_fd = xf86CheckIntOption(pInfo->options,
> +							      "fd",
> +							      -1);
>   	return device;
>   }
>
> @@ -437,7 +467,8 @@ xf86libinput_on(DeviceIntPtr dev)
>   	struct libinput *libinput = driver_context.libinput;
>   	struct libinput_device *device;
>
> -	device = xf86libinput_shared_enable(shared_device,
> +	device = xf86libinput_shared_enable(pInfo,
> +					    shared_device,
>   					    driver_data->path);
>   	if (!device)
>   		return !Success;
>


More information about the xorg-devel mailing list