[Spice-devel] [PATCH v5 03/13] GUdevClient: Do not process USB hotplug events while redirection is in progress
Dmitry Fleytman
dmitry at daynix.com
Sun Feb 28 08:44:20 UTC 2016
> On 9 Feb 2016, at 24:56 AM, Jonathon Jongsma <jjongsma at redhat.com> wrote:
>
> On Thu, 2015-10-29 at 17:27 +0200, Dmitry Fleytman wrote:
>> From: Kirill Moizik <kmoizik at redhat.com>
>>
>> USB redirection flow on Windows includes a number of reset requests issued
>> to the port that hosts the device deing redirected.
>>
>> Each port reset emulates device removal and reinsertion and produces
>> corresponding hotplug events and a number of device list updates on
>> different levels of USB stack and USB redirection engine.
>>
>> As a result, queriyng USB device list performed by spice-gtk's hotplug
>> event handler may return inconsistent results if performed in parallel
>> to redirection flow.
>>
>> This patch suppresses handling of USB hotplug events during redirection
>> and injects a simulated hotplug event after redirection completion
>> in order to properly process real device list changes in case they
>> happened during the redirection flow.
>>
>> Signed-off-by: Kirill Moizik <kmoizik at redhat.com>
>> Signed-off-by: Dmitry Fleytman <dfleytma at redhat.com>
>> ---
>> src/win-usb-dev.c | 17 +++++++++++++++++
>> 1 file changed, 17 insertions(+)
>>
>> diff --git a/src/win-usb-dev.c b/src/win-usb-dev.c
>> index 60bc434..7364ee5 100644
>> --- a/src/win-usb-dev.c
>> +++ b/src/win-usb-dev.c
>> @@ -305,10 +305,18 @@ static void g_udev_client_set_property(GObject
>> *gobject,
>> {
>> GUdevClient *self = G_UDEV_CLIENT(gobject);
>> GUdevClientPrivate *priv = self->priv;
>> + gboolean old_val;
>>
>> switch (prop_id) {
>> case PROP_REDIRECTING:
>> + old_val = priv->redirecting;
>> priv->redirecting = g_value_get_boolean(value);
>> + if (old_val && !priv->redirecting) {
>> + /* This is a redirection completion case.
>> + Inject hotplug event in case we missed device changes
>> + during redirection processing. */
>> + handle_dev_change(self);
>> + }
>> break;
>> default:
>> G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
>> @@ -409,6 +417,15 @@ static void handle_dev_change(GUdevClient *self)
>> GList *lit, *sit; /* iterators for long-list and short-list */
>> GUdevDevice *ldev, *sdev; /* devices on long-list and short-list */
>>
>> + if (priv->redirecting == TRUE) {
>> + /* On Windows, querying USB device list may return inconsistent
>> results
>> + if performed in parallel to redirection flow.
>> + A simulated hotplug event will be injected after redirection
>> + completion in order to process real device list changes that may
>> + had taken place during redirection process. */
>> + return;
>> + }
>> +
>> dev_count = g_udev_client_list_devices(self, &now_devs, &err,
>> __FUNCTION__);
>> g_return_if_fail(dev_count >= 0);
>
>
> It seems to me that this change might potentially cause us to miss hotplug
> events. Notice that the comment at the beginning of handle_dev_change() says:
>
> /* Assumes each event stands for a single device change (at most) */
>
> This becomes relevant because the implementation of this function asumes that if
> the length of the device list is unchanged from the last time it was executed,
> no change occurred. However, now that we've added an early return here, I
> believe there's a possibility for a race condition:
>
> - Start a new redirection
> - a new device is plugged in. Since priv->redirecting == TRUE, we return early
> and don't handle that change
> - a different device is unplugged. Since priv->redirecting is still TRUE, we
> return early again and don't handle the change
> - redirection completes and priv->redirecting is set to FALSE. We also trigger
> a new call to handle_dev_change(). However, since there was an added device and
> a removed device, the total number of devices is the same, and it matches the
> length of the cached device list. Therefore, no signal is emitted. But we should
> emit one remove signal and one add signal.
>
> Maybe this scenario is not a realistic possibility, I don't know.
Yes, the scenario is real.
This problem existed even before this patch. For example, when a USB hub with a few devices inserted is plugged or unplugged, only one device state change is processed.
I’m adding additional patch in front of series to address this problem.
>
> Reviewed-by: Jonathon Jongsma <jjongsma at redhat.com <mailto:jjongsma at redhat.com>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/spice-devel/attachments/20160228/a7f4aa74/attachment-0001.html>
More information about the Spice-devel
mailing list