[Spice-devel] [PATCH v7 07/14] UsbDeviceManager: Track device redirection operations in progress

Jonathon Jongsma jjongsma at redhat.com
Tue Mar 15 19:35:26 UTC 2016


Rebased patch using GTask
---------------------

>From 1ec5a45896cf0d3372cfcd426cfe1a163281c63b Mon Sep 17 00:00:00 2001
From: Kirill Moizik <kmoizik at redhat.com>
Date: Tue, 8 Mar 2016 16:05:54 +0200
Subject: [PATCH spice-gtk 07/14] UsbDeviceManager: Track device redirection
 operations in progress

During device connection, unwanted hotplug events may happen.
We need to ignore those therefore we track redirection operations
in progress.

See also comment to commit
"Do not process USB hotplug events while redirection is in progress"
that introduces corresponding filtering out logic.

Signed-off-by: Kirill Moizik <kmoizik at redhat.com>
Signed-off-by: Dmitry Fleytman <dfleytma at redhat.com>
---
 src/usb-device-manager.c | 67 ++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 54 insertions(+), 13 deletions(-)

diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c
index 394a522..8da5c0b 100644
--- a/src/usb-device-manager.c
+++ b/src/usb-device-manager.c
@@ -123,6 +123,7 @@ struct _SpiceUsbDeviceManagerPrivate {
     GUdevClient *udev;
     libusb_device **coldplug_list; /* Avoid needless reprobing during init */
 #else
+    gboolean redirecting; /* Handled by GUdevClient in the gudev case */
     libusb_hotplug_callback_handle hp_handle;
 #endif
 #ifdef G_OS_WIN32
@@ -209,10 +210,25 @@
_spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
                                                GAsyncReadyCallback callback,
                                                gpointer user_data);
 
+static
+void _connect_device_async_cb(GObject *gobject,
+                              GAsyncResult *channel_res,
+                              gpointer user_data);
+
 G_DEFINE_BOXED_TYPE(SpiceUsbDevice, spice_usb_device,
                     (GBoxedCopyFunc)spice_usb_device_ref,
                     (GBoxedFreeFunc)spice_usb_device_unref)
 
+static void
+_set_redirecting(SpiceUsbDeviceManager *self, gboolean is_redirecting)
+{
+#ifdef USE_GUDEV
+    g_object_set(self->priv->udev, "redirecting", is_redirecting, NULL);
+#else
+    self->priv->redirecting = is_redirecting;
+#endif
+}
+
 #else
 G_DEFINE_BOXED_TYPE(SpiceUsbDevice, spice_usb_device, g_object_ref,
g_object_unref)
 #endif
@@ -1165,7 +1181,7 @@ static void
spice_usb_device_manager_drv_install_cb(GObject *gobject,
     SpiceUsbDevice *device;
     UsbInstallCbInfo *cbinfo;
     GCancellable *cancellable;
-    GAsyncReadyCallback callback;
+    gpointer data;
 
     g_return_if_fail(user_data != NULL);
 
@@ -1174,8 +1190,7 @@ static void
spice_usb_device_manager_drv_install_cb(GObject *gobject,
     device      = cbinfo->device;
     installer   = cbinfo->installer;
     cancellable = cbinfo->cancellable;
-    callback    = cbinfo->callback;
-    user_data   = cbinfo->user_data;
+    data        = cbinfo->user_data;
 
     g_free(cbinfo);
 
@@ -1197,8 +1212,8 @@ static void
spice_usb_device_manager_drv_install_cb(GObject *gobject,
     _spice_usb_device_manager_connect_device_async(self,
                                                    device,
                                                    cancellable,
-                                                   callback,
-                                                   user_data);
+                                                   _connect_device_async_cb,
+                                                   data);
 
     spice_usb_device_unref(device);
 }
@@ -1530,6 +1545,8 @@
_spice_usb_device_manager_uninstall_driver_async(SpiceUsbDeviceManager *self,
 
 #endif
 
+#ifdef USE_USBREDIR
+
 static void
 _spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
                                                SpiceUsbDevice *device,
@@ -1546,7 +1563,6 @@
_spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
 
     task = g_task_new(self, cancellable, callback, user_data);
 
-#ifdef USE_USBREDIR
     SpiceUsbDeviceManagerPrivate *priv = self->priv;
     libusb_device *libdev;
     guint i;
@@ -1592,17 +1608,16 @@
_spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
         libusb_unref_device(libdev);
         return;
     }
-#endif
 
     g_task_return_new_error(task,
                             SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
                             _("No free USB channel"));
-#ifdef USE_USBREDIR
 done:
-#endif
     g_object_unref(task);
 }
 
+#endif
+
 /**
  * spice_usb_device_manager_connect_device_async:
  * @self: a #SpiceUsbDeviceManager.
@@ -1621,11 +1636,19 @@ void
spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
                                              GAsyncReadyCallback callback,
                                              gpointer user_data)
 {
+    g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self));
 
-#if defined(USE_USBREDIR) && defined(G_OS_WIN32)
+#ifdef USE_USBREDIR
+
+    GTask *task =
+        g_task_new(G_OBJECT(self), cancellable, callback, user_data);
+
+    _set_redirecting(self, TRUE);
+
+#ifdef G_OS_WIN32
     if (self->priv->use_usbclerk) {
         _spice_usb_device_manager_install_driver_async(self, device,
cancellable,
-                                                       callback, user_data);
+                                                       callback, task);
         return;
     }
 #endif
@@ -1633,8 +1656,10 @@ void
spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
     _spice_usb_device_manager_connect_device_async(self,
                                                    device,
                                                    cancellable,
-                                                   callback,
-                                                   user_data);
+                                                   _connect_device_async_cb,
+                                                   task);
+
+#endif
 }
 
 /**
@@ -1658,6 +1683,22 @@ gboolean spice_usb_device_manager_connect_device_finish(
     return g_task_propagate_boolean(task, err);
 }
 
+#ifdef USE_USBREDIR
+static
+void _connect_device_async_cb(GObject *gobject,
+                              GAsyncResult *channel_res,
+                              gpointer user_data)
+{
+    SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(gobject);
+    GTask *task = user_data;
+
+    _set_redirecting(self, FALSE);
+
+    g_task_return_boolean(task, TRUE);
+    g_object_unref(task);
+}
+#endif
+
 /**
  * spice_usb_device_manager_disconnect_device:
  * @manager: the #SpiceUsbDeviceManager manager



On Tue, 2016-03-08 at 16:05 +0200, Dmitry Fleytman wrote:

> From: Kirill Moizik <kmoizik at redhat.com>
> 
> During device connection, unwanted hotplug events may happen.
> We need to ignore those therefore we track redirection operations
> in progress.
> 
> See also comment to commit
> "Do not process USB hotplug events while redirection is in progress"
> that introduces corresponding filtering out logic.
> 
> Signed-off-by: Kirill Moizik <kmoizik at redhat.com>
> Signed-off-by: Dmitry Fleytman <dfleytma at redhat.com>
> ---
>  src/usb-device-manager.c | 69 +++++++++++++++++++++++++++++++++++++++--------
> -
>  1 file changed, 56 insertions(+), 13 deletions(-)
> 
> diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c
> index 4d376b6..fc0f15f 100644
> --- a/src/usb-device-manager.c
> +++ b/src/usb-device-manager.c
> @@ -122,6 +122,7 @@ struct _SpiceUsbDeviceManagerPrivate {
>      GUdevClient *udev;
>      libusb_device **coldplug_list; /* Avoid needless reprobing during init */
>  #else
> +    gboolean redirecting; /* Handled by GUdevClient in the gudev case */
>      libusb_hotplug_callback_handle hp_handle;
>  #endif
>  #ifdef G_OS_WIN32
> @@ -208,10 +209,25 @@
> _spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
>                                                 GAsyncReadyCallback callback,
>                                                 gpointer user_data);
>  
> +static
> +void _connect_device_async_cb(GObject *gobject,
> +                              GAsyncResult *channel_res,
> +                              gpointer user_data);
> +
>  G_DEFINE_BOXED_TYPE(SpiceUsbDevice, spice_usb_device,
>                      (GBoxedCopyFunc)spice_usb_device_ref,
>                      (GBoxedFreeFunc)spice_usb_device_unref)
>  
> +static void
> +_set_redirecting(SpiceUsbDeviceManager *self, gboolean is_redirecting)
> +{
> +#ifdef USE_GUDEV
> +    g_object_set(self->priv->udev, "redirecting", is_redirecting, NULL);
> +#else
> +    self->priv->redirecting = is_redirecting;
> +#endif
> +}
> +
>  #else
>  G_DEFINE_BOXED_TYPE(SpiceUsbDevice, spice_usb_device, g_object_ref,
> g_object_unref)
>  #endif
> @@ -1135,7 +1151,7 @@ static void
> spice_usb_device_manager_drv_install_cb(GObject *gobject,
>      SpiceUsbDevice *device;
>      UsbInstallCbInfo *cbinfo;
>      GCancellable *cancellable;
> -    GAsyncReadyCallback callback;
> +    gpointer data;
>  
>      g_return_if_fail(user_data != NULL);
>  
> @@ -1144,8 +1160,7 @@ static void
> spice_usb_device_manager_drv_install_cb(GObject *gobject,
>      device      = cbinfo->device;
>      installer   = cbinfo->installer;
>      cancellable = cbinfo->cancellable;
> -    callback    = cbinfo->callback;
> -    user_data   = cbinfo->user_data;
> +    data        = cbinfo->user_data;
>  
>      g_free(cbinfo);
>  
> @@ -1167,8 +1182,8 @@ static void
> spice_usb_device_manager_drv_install_cb(GObject *gobject,
>      _spice_usb_device_manager_connect_device_async(self,
>                                                     device,
>                                                     cancellable,
> -                                                   callback,
> -                                                   user_data);
> +                                                   _connect_device_async_cb,
> +                                                   data);
>  
>      spice_usb_device_unref(device);
>  }
> @@ -1496,6 +1511,8 @@
> _spice_usb_device_manager_uninstall_driver_async(SpiceUsbDeviceManager *self,
>  
>  #endif
>  
> +#ifdef USE_USBREDIR
> +
>  static void
>  _spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
>                                                 SpiceUsbDevice *device,
> @@ -1513,7 +1530,6 @@
> _spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
>      result = g_simple_async_result_new(G_OBJECT(self), callback, user_data,
>                                
>  spice_usb_device_manager_connect_device_async);
>  
> -#ifdef USE_USBREDIR
>      SpiceUsbDeviceManagerPrivate *priv = self->priv;
>      libusb_device *libdev;
>      guint i;
> @@ -1559,18 +1575,17 @@
> _spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
>          libusb_unref_device(libdev);
>          return;
>      }
> -#endif
>  
>      g_simple_async_result_set_error(result,
>                              SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
>                              _("No free USB channel"));
> -#ifdef USE_USBREDIR
>  done:
> -#endif
>      g_simple_async_result_complete_in_idle(result);
>      g_object_unref(result);
>  }
>  
> +#endif
> +
>  /**
>   * spice_usb_device_manager_connect_device_async:
>   * @self: a #SpiceUsbDeviceManager.
> @@ -1589,11 +1604,20 @@ void
> spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
>                                               GAsyncReadyCallback callback,
>                                               gpointer user_data)
>  {
> +    g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self));
>  
> -#if defined(USE_USBREDIR) && defined(G_OS_WIN32)
> +#ifdef USE_USBREDIR
> +
> +    GSimpleAsyncResult *result =
> +        g_simple_async_result_new(G_OBJECT(self), callback, user_data,
> +                                 
>  spice_usb_device_manager_connect_device_async);
> +
> +    _set_redirecting(self, TRUE);
> +
> +#ifdef G_OS_WIN32
>      if (self->priv->use_usbclerk) {
>          _spice_usb_device_manager_install_driver_async(self, device,
> cancellable,
> -                                                       callback, user_data);
> +                                                       callback, result);
>          return;
>      }
>  #endif
> @@ -1601,10 +1625,13 @@ void
> spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
>      _spice_usb_device_manager_connect_device_async(self,
>                                                     device,
>                                                     cancellable,
> -                                                   callback,
> -                                                   user_data);
> +                                                   _connect_device_async_cb,
> +                                                   result);
> +
> +#endif
>  }
>  
> +
>  /**
>   * spice_usb_device_manager_connect_device_finish:
>   * @self: a #SpiceUsbDeviceManager.
> @@ -1630,6 +1657,22 @@ gboolean
> spice_usb_device_manager_connect_device_finish(
>      return TRUE;
>  }
>  
> +#ifdef USE_USBREDIR
> +static
> +void _connect_device_async_cb(GObject *gobject,
> +                              GAsyncResult *channel_res,
> +                              gpointer user_data)
> +{
> +    SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(gobject);
> +    GSimpleAsyncResult *result = user_data;
> +
> +    _set_redirecting(self, FALSE);
> +
> +    g_simple_async_result_complete(result);
> +    g_object_unref(result);
> +}
> +#endif
> +
>  /**
>   * spice_usb_device_manager_disconnect_device:
>   * @manager: the #SpiceUsbDeviceManager manager


More information about the Spice-devel mailing list