[Spice-devel] [PATCH v4 07/16] usbredir: Spawn a different thread for device redirection flow

Christophe Fergeau cfergeau at redhat.com
Wed Sep 23 05:08:14 PDT 2015


On Sun, Aug 16, 2015 at 03:35:44PM +0300, Dmitry Fleytman wrote:
> From: Kirill Moizik <kmoizik at redhat.com>
> 
> On Windows when using usbdk, opening and closing USB device handle,
> i.e. calling libusb_open()/libusb_unref_device() can block for a few
> seconds (3-5 second more specifically on patch author's HW).
> 
> libusb_open() is called by spice_usbredir_channel_open_device().
> 
> libusb_unref_device() is called implicitely via
> usbredirhost_set_device(..., NULL) from
> spice_usbredir_channel_disconnect_device().

Is this libusb_unref_device() or libusb_close() which can block?

spice_usbredir_channel_disconnect_device() does:

/* This also closes the libusb handle we passed from open_device */
usbredirhost_set_device(priv->host, NULL);
libusb_unref_device(priv->device);

so the libusb_close() call is done by usbredirhost_set_device() while
the libusb_unref_device() call is done explicitly in
spice_usbredir_channel_disconnect_device()

If what is blocking is libusb_unref_device(), I would not bother making
disconnect() async by running in a thread, but I'd just spawn a thread
to do the libusb_unref_device() call. I don't think it's important that
we wait until the call completes, so _disconnect() would not need to
change apart from this delayed unref.

If the blocking call is libusb_close(), I don't know if the same
approach can be used with usbredirhost_set_device? Has this been tried?

Christophe


> 
> Both these calls happen on the main thread. If it blocks,
> this causes the UI to freeze.
> 
> This commit makes sure libusb_open() is called from a different
> thread to avoid blocking the mainloop freezes when usbdk is used.
> 
> Following commits also move usbredirhost_set_device(..., NULL) call
> to the different threads.
> 
> Since this commit introduces additional execution contexts running in
> parallell to the main thread threre are thread safety concerns to be secured.
> Mainly there are 3 types of objects accessed by newly introduced threads:
>   1. libusb contexts
>   2. usbredir context
>   3. redirection channels
> 
> Fortunately libusb accesses either thread safe of already performed by
> a separate thread and protected by locks as needed.
> 
> As for channels and usbredir, in order to achieve thread safety this patch introduces
> additional locks and references, namely:
> 
> 1. To make sure channel objects are not disposed while redirection in progress,
>    they are referenced on flow start and unreferenced on flow completion;
> 2. Channel objects data accesses from different threads protected with a
>    new lock (flows_mutex);
> 3. Handling usbredir messages protected by the same new lock in order to
>    ensure there are no messages processing flows in progres when device gets
>    connected or disconneced.
> 
> Signed-off-by: Kirill Moizik <kmoizik at redhat.com>
> Signed-off-by: Dmitry Fleytman <dfleytma at redhat.com>
> ---
>  src/channel-usbredir.c | 41 ++++++++++++++++++++++++++++++-----------
>  1 file changed, 30 insertions(+), 11 deletions(-)
> 
> diff --git a/src/channel-usbredir.c b/src/channel-usbredir.c
> index bbfd2b0..44da3ce 100644
> --- a/src/channel-usbredir.c
> +++ b/src/channel-usbredir.c
> @@ -315,6 +315,27 @@ static void spice_usbredir_channel_open_acl_cb(
>  }
>  #endif
>  
> +#ifndef USE_POLKIT
> +static void
> +_open_device_async_cb(GSimpleAsyncResult *simple,
> +                      GObject *object,
> +                      GCancellable *cancellable)
> +{
> +    GError *err = NULL;
> +    SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(object);
> +    SpiceUsbredirChannelPrivate *priv = channel->priv;
> +    g_mutex_lock(priv->flows_mutex);
> +    if (!spice_usbredir_channel_open_device(channel, &err)) {
> +        g_simple_async_result_take_error(simple, err);
> +        libusb_unref_device(priv->device);
> +        priv->device = NULL;
> +        g_boxed_free(spice_usb_device_get_type(), priv->spice_device);
> +        priv->spice_device = NULL;
> +     }
> +    g_mutex_unlock(priv->flows_mutex);
> +}
> +#endif
> +
>  G_GNUC_INTERNAL
>  void spice_usbredir_channel_connect_device_async(
>                                            SpiceUsbredirChannel *channel,
> @@ -324,15 +345,14 @@ void spice_usbredir_channel_connect_device_async(
>                                            GAsyncReadyCallback   callback,
>                                            gpointer              user_data)
>  {
> -    SpiceUsbredirChannelPrivate *priv = channel->priv;
> +    SpiceUsbredirChannelPrivate *priv;
>      GSimpleAsyncResult *result;
> -#if ! USE_POLKIT
> -    GError *err = NULL;
> -#endif
>  
>      g_return_if_fail(SPICE_IS_USBREDIR_CHANNEL(channel));
>      g_return_if_fail(device != NULL);
>  
> +    priv = channel->priv;
> +
>      CHANNEL_DEBUG(channel, "connecting usb channel %p", channel);
>  
>      result = g_simple_async_result_new(G_OBJECT(channel), callback, user_data,
> @@ -369,13 +389,12 @@ void spice_usbredir_channel_connect_device_async(
>                                    channel);
>      return;
>  #else
> -    if (!spice_usbredir_channel_open_device(channel, &err)) {
> -        g_simple_async_result_take_error(result, err);
> -        libusb_unref_device(priv->device);
> -        priv->device = NULL;
> -        g_boxed_free(spice_usb_device_get_type(), priv->spice_device);
> -        priv->spice_device = NULL;
> -    }
> +    g_simple_async_result_run_in_thread(result,
> +                                        _open_device_async_cb,
> +                                        G_PRIORITY_DEFAULT,
> +                                        cancellable);
> +    g_object_unref(result);
> +    return;
>  #endif
>  
>  done:
> -- 
> 2.4.3
> 
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/spice-devel/attachments/20150923/9b619be8/attachment.sig>


More information about the Spice-devel mailing list