linux_usbfs: Deal with receiving POLLERR before all transfers have completed
authorHans de Goede <hdegoede@redhat.com>
Tue, 7 Jun 2016 10:12:38 +0000 (12:12 +0200)
committerNathan Hjelm <hjelmn@me.com>
Wed, 17 Aug 2016 18:52:40 +0000 (12:52 -0600)
The linux kernel will set its internal device state to USB_STATE_NOTATTACHED
as soon as it detects the disconnect, and then start a worker thread to
deal with the actual disconnection, kill outstanding urbs, etc.

The usbfs poll implementation will return POLL_ERR as soon as
ps->dev->state == USB_STATE_NOTATTACHED. The kernel will not wakeup
the poll until it is done with processing the disconnection. But if
we happen to call poll() between the state change and the disconnection
being fully processed, we may not be able to reap all outstanding transfers,
even on kernels with the USBFS_CAP_REAP_AFTER_DISCONNECT capability.

This commit deals with this by trying to reap as many transfers as possible
on disconnect on USBFS_CAP_REAP_AFTER_DISCONNECT capable kernels and then
calling usbi_handle_disconnect(handle) to deal with any remaining ones.
On USBFS_CAP_REAP_AFTER_DISCONNECT capable kernels this will be a no-op
unless we hit the race.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
libusb/os/linux_usbfs.c
libusb/version_nano.h

index 0689894..9cbeb80 100644 (file)
@@ -2638,10 +2638,14 @@ static int op_handle_events(struct libusb_context *ctx,
                                                handle->dev->device_address);
                        usbi_mutex_static_unlock(&linux_hotplug_lock);
 
-                       if (!(hpriv->caps & USBFS_CAP_REAP_AFTER_DISCONNECT)) {
-                               usbi_handle_disconnect(handle);
-                               continue;
+                       if (hpriv->caps & USBFS_CAP_REAP_AFTER_DISCONNECT) {
+                               do {
+                                       r = reap_for_handle(handle);
+                               } while (r == 0);
                        }
+
+                       usbi_handle_disconnect(handle);
+                       continue;
                }
 
                do {
index bb7624f..b394a2e 100644 (file)
@@ -1 +1 @@
-#define LIBUSB_NANO 11137
+#define LIBUSB_NANO 11138