From 00e36c829fe87a3d285d7a774eb8a1ca8797d0c0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 7 Jun 2016 12:12:38 +0200 Subject: linux_usbfs: Deal with receiving POLLERR before all transfers have completed 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 --- libusb/os/linux_usbfs.c | 10 +++++++--- libusb/version_nano.h | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 0689894..9cbeb80 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -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 { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index bb7624f..b394a2e 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11137 +#define LIBUSB_NANO 11138 -- cgit v1.2.1