Do not call timerfd functions when timerfd is not being used
authorPeter Stuge <peter@stuge.se>
Mon, 13 Feb 2012 15:59:51 +0000 (16:59 +0100)
committerPeter Stuge <peter@stuge.se>
Mon, 13 Feb 2012 19:00:35 +0000 (20:00 +0100)
When libusb was built with timerfd support but used on a system
without timerfd support the library would hang indefinitely on
completion of the first transfer, since timerfd functions were
being called unconditionally and the error returned when timerfd
was not being used caused a confused internal state.

Many thanks to Ivo Smits for looking into the issue, proposing
an initial solution, and helping with testing! Fixes #73.

libusb/io.c

index c4b3635..bb6e275 100644 (file)
@@ -1439,7 +1439,7 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
                USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
        struct libusb_context *ctx = TRANSFER_CTX(transfer);
        uint8_t flags;
-       int r;
+       int r = 0;
 
        /* FIXME: could be more intelligent with the timerfd here. we don't need
         * to disarm the timerfd if there was no timer running, and we only need
@@ -1448,12 +1448,13 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
 
        usbi_mutex_lock(&ctx->flying_transfers_lock);
        list_del(&itransfer->list);
-       r = arm_timerfd_for_next_timeout(ctx);
+       if (usbi_using_timerfd(ctx))
+               r = arm_timerfd_for_next_timeout(ctx);
        usbi_mutex_unlock(&ctx->flying_transfers_lock);
 
-       if (r < 0) {
-               return r;
-       } else if (r == 0) {
+       if (usbi_using_timerfd(ctx)) {
+               if (r < 0)
+                       return r;
                r = disarm_timerfd(ctx);
                if (r < 0)
                        return r;