<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 1 Mar 2016, at 24:06 AM, Jonathon Jongsma <<a href="mailto:jjongsma@redhat.com" class="">jjongsma@redhat.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">On Sun, 2016-02-28 at 11:54 +0200, Dmitry Fleytman wrote:</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">This patch fixes device list change notification handing<br class="">logic for cases when more than one device being plugged<br class="">or unplugged simultaneously.<br class=""><br class="">The simplest way to reproduce the problematic scenario<br class="">is (un)plugging of a usb HUB with a few devices inserted.<br class=""><br class="">Signed-off-by: Dmitry Fleytman <<a href="mailto:dmitry@daynix.com" class="">dmitry@daynix.com</a>><br class="">---<br class="">src/win-usb-dev.c | 82 +++++++++++++++++++-----------------------------------<br class="">-<br class="">1 file changed, 28 insertions(+), 54 deletions(-)<br class=""><br class="">diff --git a/src/win-usb-dev.c b/src/win-usb-dev.c<br class="">index 1e4b2d6..1b4d353 100644<br class="">--- a/src/win-usb-dev.c<br class="">+++ b/src/win-usb-dev.c<br class="">@@ -34,7 +34,6 @@<br class=""><br class="">struct _GUdevClientPrivate {<br class=""> libusb_context *ctx;<br class="">- gssize udev_list_size;<br class=""> GList *udev_list;<br class=""> HWND hwnd;<br class="">};<br class="">@@ -196,9 +195,7 @@ g_udev_client_initable_init(GInitable *initable,<br class="">GCancellable *cancellable,<br class=""> }<br class=""><br class=""> /* get initial device list */<br class="">- priv->udev_list_size = g_udev_client_list_devices(self, &priv->udev_list,<br class="">- err, __FUNCTION__);<br class="">- if (priv->udev_list_size < 0) {<br class="">+ if (g_udev_client_list_devices(self, &priv->udev_list, err, __FUNCTION__)<br class="">< 0) {<br class=""> goto g_udev_client_init_failed;<br class=""> }<br class=""><br class="">@@ -339,74 +336,51 @@ static gboolean gudev_devices_are_equal(GUdevDevice *a,<br class="">GUdevDevice *b)<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Immediately above this line is the following comment:</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">/* Assumes each event stands for a single device change (at most) */</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Since you're changing the function to handle multiple insertions or removals at</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">once, we should probably remove this comment.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote><div><br class=""></div><div>Right, I forgot to drop it. Removed.</div><br class=""><blockquote type="cite" class=""><div class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">static void handle_dev_change(GUdevClient *self)<br class="">{<br class=""> GUdevClientPrivate *priv = self->priv;<br class="">- GUdevDevice *changed_dev = NULL;<br class="">- ssize_t dev_count;<br class="">- int is_dev_change;<br class=""> GError *err = NULL;<br class=""> GList *now_devs = NULL;<br class="">- GList *llist, *slist; /* long-list and short-list*/<br class="">- GList *lit, *sit; /* iterators for long-list and short-list */<br class="">- GUdevDevice *ldev, *sdev; /* devices on long-list and short-list */<br class="">+ GList *prev, *curr; /* iterators for previous and current device lists */<br class=""><br class="">- dev_count = g_udev_client_list_devices(self, &now_devs, &err,<br class="">- __FUNCTION__);<br class="">- g_return_if_fail(dev_count >= 0);<br class="">-<br class="">- SPICE_DEBUG("number of current devices %"G_GSSIZE_FORMAT<br class="">- ", I know about %"G_GSSIZE_FORMAT" devices",<br class="">- dev_count, priv->udev_list_size);<br class="">-<br class="">- is_dev_change = dev_count - priv->udev_list_size;<br class="">- if (is_dev_change == 0) {<br class="">- g_udev_client_free_device_list(&now_devs);<br class="">+ if(g_udev_client_list_devices(self, &now_devs, &err, __FUNCTION__) < 0) {<br class="">+ g_warning("could not retrieve device list");<br class=""> return;<br class=""> }<br class=""><br class="">- if (is_dev_change > 0) {<br class="">- llist = now_devs;<br class="">- slist = priv->udev_list;<br class="">- } else {<br class="">- llist = priv->udev_list;<br class="">- slist = now_devs;<br class="">- }<br class="">-<br class="">- g_udev_device_print_list(llist, "handle_dev_change: long list:");<br class="">- g_udev_device_print_list(slist, "handle_dev_change: short list:");<br class="">+ g_udev_device_print_list(now_devs, "handle_dev_change: current list:");<br class="">+ g_udev_device_print_list(priv->udev_list, "handle_dev_change: previous<br class="">list:");<br class=""><br class="">- /* Go over the longer list */<br class="">- for (lit = g_list_first(llist); lit != NULL; lit=g_list_next(lit)) {<br class="">- ldev = lit->data;<br class="">- /* Look for dev in the shorther list */<br class="">- for (sit = g_list_first(slist); sit != NULL; sit=g_list_next(sit)) {<br class="">- sdev = sit->data;<br class="">- if (gudev_devices_are_equal(ldev, sdev))<br class="">+ /* Unregister devices that are not present anymore */<br class="">+ for (prev = g_list_first(priv->udev_list); prev != NULL; prev =<br class="">g_list_next(prev)) {<br class="">+ /* Look for dev in the current list */<br class="">+ for (curr = g_list_first(now_devs); curr != NULL; curr =<span class="Apple-converted-space"> </span><br class="">g_list_next(curr)) {<br class="">+ if (gudev_devices_are_equal(prev->data, curr->data))<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">g_list_find_custom() is a possibility here</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote><div><br class=""></div><div><br class=""></div><div>Ok.</div><br class=""><blockquote type="cite" class=""><div class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""> break;<br class=""> }<br class="">- if (sit == NULL) {<br class="">- /* Found a device which appears only in the longer list */<br class="">- changed_dev = ldev;<br class="">- break;<br class="">+<br class="">+ if (curr == NULL) {<br class="">+ /* Found a device that was removed */<br class="">+ g_udev_device_print(prev->data, "<<< USB device removed");<br class="">+ g_signal_emit(self, signals[UEVENT_SIGNAL], 0, "remove", prev<br class="">->data);<br class=""> }<br class=""> }<br class=""><br class="">- if (!changed_dev) {<br class="">- g_warning("couldn't find any device change");<br class="">- goto leave;<br class="">- }<br class="">+ /* Register newly inserted devices */<br class="">+ for (curr = g_list_first(now_devs); curr != NULL; curr =<br class="">g_list_next(curr)) {<br class="">+ /* Look for dev in the previous list */<br class="">+ for (prev = g_list_first(priv->udev_list); prev != NULL; prev =<br class="">g_list_next(prev)) {<br class="">+ if (gudev_devices_are_equal(prev->data, curr->data))<br class="">+ break;<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">and here</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote><div><br class=""></div><div>Actually these nested loops are similar in both cases so in the next version I moved those to a separate function and used g_list_find_custom() as you suggested.</div><br class=""><blockquote type="cite" class=""><div class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">+ }<br class=""><br class="">- if (is_dev_change > 0) {<br class="">- g_udev_device_print(changed_dev, ">>> USB device inserted");<br class="">- g_signal_emit(self, signals[UEVENT_SIGNAL], 0, "add", changed_dev);<br class="">- } else {<br class="">- g_udev_device_print(changed_dev, "<<< USB device removed");<br class="">- g_signal_emit(self, signals[UEVENT_SIGNAL], 0, "remove",<br class="">changed_dev);<br class="">+ if (prev == NULL) {<br class="">+ /* Found a device that was inserted */<br class="">+ g_udev_device_print(curr->data, ">>> USB device inserted");<br class="">+ g_signal_emit(self, signals[UEVENT_SIGNAL], 0, "add", curr<br class="">->data);<br class="">+ }<br class=""> }<br class=""><br class="">-leave:<br class=""> /* keep most recent info: free previous list, and keep current list */<br class=""> g_udev_client_free_device_list(&priv->udev_list);<br class=""> priv->udev_list = now_devs;<br class="">- priv->udev_list_size = dev_count;<br class="">}<br class=""><br class="">static LRESULT CALLBACK wnd_proc(HWND hwnd, UINT message, WPARAM wparam,<br class="">LPARAM lparam)<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Acked-by: Jonathon Jongsma <</span><a href="mailto:jjongsma@redhat.com" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">jjongsma@redhat.com</a><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">></span></div></blockquote></div><br class=""></body></html>