<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jul 7, 2015 at 3:51 PM, Christophe Fergeau <span dir="ltr"><<a href="mailto:cfergeau@redhat.com" target="_blank">cfergeau@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Mon, Jul 06, 2015 at 08:59:06PM +0300, Kirill Moizik wrote:<br>
> we will spawn a separate thread to disconnect usb device, when finish we will update widget to allow further<br>
> usb redirection operations<br>
> 1) expose spice_usbredir_channel_connect_device_async function for asynchronous disconnect<br>
> 2) threads synchronization<br>
<br>
</span>Honestly, moving non-trivial existing functions from running in the main<br>
thread to running in a separate thread with very little locking added,<br>
and no high level explanation as to why everything will be fine and<br>
nothing can be racy is very scary... One example below:<br></blockquote><div><br></div><div>I understand, I new to this project so i can't give you high level explanation why there is no races. I am aware  there could be races, so i spent time trying to find it. I tried few Os's on different hardware,  with and without spice/gtk debugging flags to change timing of flows to see if it will fail, but l it worked for me. Also i was trying to add another locks in suspicious places, but it led to deadlocks.  Do you have any ideas how to prove quality of those patches ?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div><div class="h5"><br>
><br>
> Signed-off-by: Kirill Moizik <<a href="mailto:kmoizik@redhat.com">kmoizik@redhat.com</a>><br>
> ---<br>
>  src/channel-usbredir-priv.h |  8 ++++-<br>
>  src/channel-usbredir.c      | 79 ++++++++++++++++++++++++++++++++++++++-------<br>
>  src/map-file                |  1 +<br>
>  src/usb-device-manager.c    | 62 ++++++++++++++++++++++++++++++++++-<br>
>  src/usb-device-manager.h    |  8 +++++<br>
>  src/usb-device-widget.c     | 19 +++++++++--<br>
>  6 files changed, 161 insertions(+), 16 deletions(-)<br>
><br>
> diff --git a/src/channel-usbredir-priv.h b/src/channel-usbredir-priv.h<br>
> index 2c4c6f7..c3ff158 100644<br>
> --- a/src/channel-usbredir-priv.h<br>
> +++ b/src/channel-usbredir-priv.h<br>
> @@ -33,6 +33,10 @@ G_BEGIN_DECLS<br>
>  void spice_usbredir_channel_set_context(SpiceUsbredirChannel *channel,<br>
>                                          libusb_context       *context);<br>
><br>
> +void spice_usbredir_channel_disconnect_device_async(SpiceUsbredirChannel *channel,<br>
> +                                                    GSimpleAsyncResult *simple,<br>
> +                                                    GCancellable *cancellable);<br>
> +<br>
>  /* Note the context must be set, and the channel must be brought up<br>
>     (through spice_channel_connect()), before calling this. */<br>
>  void spice_usbredir_channel_connect_device_async(<br>
> @@ -47,7 +51,9 @@ gboolean spice_usbredir_channel_connect_device_finish(<br>
>                                          GAsyncResult         *res,<br>
>                                          GError              **err);<br>
><br>
> -void spice_usbredir_channel_disconnect_device(SpiceUsbredirChannel *channel);<br>
> +void spice_usbredir_channel_disconnect_device(GSimpleAsyncResult *simple,<br>
> +                                              GObject *object,<br>
> +                                              GCancellable *cancellable);<br>
><br>
>  libusb_device *spice_usbredir_channel_get_device(SpiceUsbredirChannel *channel);<br>
><br>
> diff --git a/src/channel-usbredir.c b/src/channel-usbredir.c<br>
> index e7d5949..1e78350 100644<br>
> --- a/src/channel-usbredir.c<br>
> +++ b/src/channel-usbredir.c<br>
> @@ -79,6 +79,7 @@ struct _SpiceUsbredirChannelPrivate {<br>
>      GSimpleAsyncResult *result;<br>
>      SpiceUsbAclHelper *acl_helper;<br>
>  #endif<br>
> +    void* redirect_mutex;<br>
<br>
</div></div>usbredir_alloc_lock returns a void* only because that's what usbredir<br>
expects. Let's just cast it to GMutex * here, and use<br>
g_mutex_lock/unlock.<br></blockquote><div><br></div><div>Ok, will fix it <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
[snip]<br>
<span class=""><br>
> @@ -440,7 +491,9 @@ void spice_usbredir_channel_disconnect_device(SpiceUsbredirChannel *channel)<br>
>                      spice_usb_device_manager_get(session, NULL));<br>
>          }<br>
>          /* This also closes the libusb handle we passed from open_device */<br>
> +        usbredir_lock_lock(channel->priv->redirect_mutex);<br>
>          usbredirhost_set_device(priv->host, NULL);<br>
> +        usbredir_unlock_lock(channel->priv->redirect_mutex);<br>
>          libusb_unref_device(priv->device);<br>
>          priv->device = NULL;<br>
>          g_boxed_free(spice_usb_device_get_type(), priv->spice_device);<br>
</span>>          priv->spice_device = NULL;<br>
<span class="">><br>
> @@ -652,7 +705,9 @@ static void usbredir_handle_msg(SpiceChannel *c, SpiceMsgIn *in)<br>
>      priv->read_buf = buf;<br>
>      priv->read_buf_size = size;<br>
><br>
> +    usbredir_lock_lock(priv->redirect_mutex);<br>
>      r = usbredirhost_read_guest_data(priv->host);<br>
> +    usbredir_unlock_lock(priv->redirect_mutex);<br>
>      if (r != 0) {<br>
>          SpiceUsbDevice *spice_device = priv->spice_device;<br>
>          gchar *desc;<br>
<br>
</span>>          GError *err;<br>
<br>
>          g_return_if_fail(spice_device != NULL);<br>
<br>
The 2 hunks I kept are the only 2 places loking/unlocking<br>
redirect_mutex, I assume this means they can race with each other.<br>
If that's true, then we can get in a situation where 2nd hunk code runs<br>
till<br>
      if (r != 0) {<br>
with r != 0, then 1st hunk runs and sets priv->spice_device to NULL,<br>
then 2nd hunk resumes, and we trigger the g_return_if_fail() (which<br>
usually is used to indicate a programming error)<br></blockquote><div><br></div><div>we can expand critical section in this case, is it bad idea?<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<span class="HOEnZb"><font color="#888888"><br>
Christophe<br>
</font></span></blockquote></div><br></div></div>