core: Record when a transfer timeout has been handled
authorChris Dickens <christopher.a.dickens@gmail.com>
Sat, 22 Aug 2015 07:41:58 +0000 (00:41 -0700)
committerChris Dickens <christopher.a.dickens@gmail.com>
Thu, 3 Sep 2015 02:47:15 +0000 (19:47 -0700)
Commit efd02e73 introduced a bug where transfers that timed out
would be handled repeatedly if the cancellation was not successful.
This behavior blocks any event handling from occurring.

This commit adds a new transfer flag to record whether a timeout has
been handled.

Thanks to Jeffrey Nichols for reporting this.

Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
libusb/io.c
libusb/libusbi.h
libusb/version_nano.h

index 420f87a..082441c 100644 (file)
@@ -1332,7 +1332,7 @@ static int arm_timerfd_for_next_timeout(struct libusb_context *ctx)
                        goto disarm;
 
                /* act on first transfer that is not already cancelled */
-               if (!(transfer->flags & USBI_TRANSFER_TIMED_OUT)) {
+               if (!(transfer->flags & USBI_TRANSFER_TIMEOUT_HANDLED)) {
                        int r;
                        const struct itimerspec it = { {0, 0},
                                { cur_tv->tv_sec, cur_tv->tv_usec * 1000 } };
@@ -1944,6 +1944,7 @@ static void handle_timeout(struct usbi_transfer *itransfer)
                USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
        int r;
 
+       itransfer->flags |= USBI_TRANSFER_TIMEOUT_HANDLED;
        r = libusb_cancel_transfer(transfer);
        if (r == 0)
                itransfer->flags |= USBI_TRANSFER_TIMED_OUT;
@@ -1979,7 +1980,7 @@ static int handle_timeouts_locked(struct libusb_context *ctx)
                        return 0;
 
                /* ignore timeouts we've already handled */
-               if (transfer->flags & (USBI_TRANSFER_TIMED_OUT | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
+               if (transfer->flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
                        continue;
 
                /* if transfer has non-expired timeout, nothing more to do */
@@ -2506,7 +2507,7 @@ int API_EXPORTED libusb_get_next_timeout(libusb_context *ctx,
 
        /* find next transfer which hasn't already been processed as timed out */
        list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
-               if (transfer->flags & (USBI_TRANSFER_TIMED_OUT | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
+               if (transfer->flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
                        continue;
 
                /* if we've reached transfers of infinte timeout, we're done looking */
index cbd1150..822612e 100644 (file)
@@ -435,6 +435,9 @@ enum usbi_transfer_flags {
 
        /* Completion handler has run */
        USBI_TRANSFER_COMPLETED = 1 << 6,
+
+       /* The transfer timeout has been handled */
+       USBI_TRANSFER_TIMEOUT_HANDLED = 1 << 7,
 };
 
 #define USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \
index 58b4c88..a1bec0a 100644 (file)
@@ -1 +1 @@
-#define LIBUSB_NANO 10997
+#define LIBUSB_NANO 10998