From 62b6a91a0d760ed57bc3d19a65d3b11a9c780b12 Mon Sep 17 00:00:00 2001 From: Jindrich Novy Date: Aug 02 2008 06:31:18 +0000 Subject: - apply patch from Graeme Gill to fix concurrency timeout handling (#456811) --- diff --git a/libusb-0.1.12-concurrency-timeout.patch b/libusb-0.1.12-concurrency-timeout.patch new file mode 100644 index 0000000..f4939f8 --- /dev/null +++ b/libusb-0.1.12-concurrency-timeout.patch @@ -0,0 +1,160 @@ +--- libusb-0.1.12/linux.c 2008-07-01 12:24:36.000000000 +0200 ++++ libusb/linux.c 2008-06-30 15:21:09.000000000 +0200 +@@ -166,7 +166,7 @@ + int bytesdone = 0, requested; + struct timeval tv, tv_ref, tv_now; + struct usb_urb *context; +- int ret, waiting; ++ int ret, tdout, rc; + + /* + * HACK: The use of urb.usercontext is a hack to get threaded applications +@@ -184,7 +184,6 @@ + gettimeofday(&tv_ref, NULL); + tv_ref.tv_sec = tv_ref.tv_sec + timeout / 1000; + tv_ref.tv_usec = tv_ref.tv_usec + (timeout % 1000) * 1000; +- + if (tv_ref.tv_usec > 1000000) { + tv_ref.tv_usec -= 1000000; + tv_ref.tv_sec++; +@@ -216,65 +215,67 @@ + FD_ZERO(&writefds); + FD_SET(dev->fd, &writefds); + +-restart: +- waiting = 1; +- context = NULL; +- while (!urb.usercontext && ((ret = ioctl(dev->fd, IOCTL_USB_REAPURBNDELAY, &context)) == -1) && waiting) { +- tv.tv_sec = 0; +- tv.tv_usec = 1000; // 1 msec +- select(dev->fd + 1, NULL, &writefds, NULL, &tv); //sub second wait +- +- if (timeout) { +- /* compare with actual time, as the select timeout is not that precise */ ++ /* Now wait for our urb to turn up */ ++ tdout = 0; ++ for (;;) { ++ ret = 0; ++ if (urb.usercontext) { ++ break; /* Another thread found our URB for us */ ++ } ++ context = NULL; ++ ret = ioctl(dev->fd, IOCTL_USB_REAPURBNDELAY, &context); ++ if (ret == 0 && context) { /* Found something */ ++ if (context == &urb) { /* Got the URB we were waiting for */ ++ break; ++ } ++ /* Must be some other threads. Mark it and keep waiting for ours */ ++ context->usercontext = URB_USERCONTEXT_COOKIE; ++ } else { ++ if (errno != EAGAIN) { ++ fprintf(stderr, "error reaping URB: %s", strerror(errno)); ++ break; ++ } ++ /* We are still waiting. See if we've timed out */ + gettimeofday(&tv_now, NULL); +- + if ((tv_now.tv_sec > tv_ref.tv_sec) || +- ((tv_now.tv_sec == tv_ref.tv_sec) && (tv_now.tv_usec >= tv_ref.tv_usec))) +- waiting = 0; ++ ((tv_now.tv_sec == tv_ref.tv_sec) && (tv_now.tv_usec >= tv_ref.tv_usec))) { ++ if (tdout) { /* Second time we've timed out. Discard must have failed */ ++ break; ++ } ++ tdout = 1; ++ /* Discard our URB and continue waiting a while for it to turn up */ ++ ret = ioctl(dev->fd, IOCTL_USB_DISCARDURB, &urb); ++ if (ret < 0 && errno != EINVAL && usb_debug >= 1) { ++ fprintf(stderr, "error discarding URB: %s", strerror(errno)); ++ } ++ /* Allow another 100msec for discard to occur. Should normally happen faster than this. */ ++ tv_ref.tv_sec = tv_now.tv_sec + 100 / 1000; ++ tv_ref.tv_usec = tv_now.tv_usec + (100 % 1000) * 1000; ++ if (tv_ref.tv_usec > 1000000) { ++ tv_ref.tv_usec -= 1000000; ++ tv_ref.tv_sec++; ++ } ++ } + } ++ /* Sleep for 2msec to wait for things to happen */ ++ tv.tv_sec = 0; ++ tv.tv_usec = 2000; /* 2 msec */ ++ select(dev->fd + 1, NULL, &writefds, NULL, &tv); + } + +- if (context && context != &urb) { +- context->usercontext = URB_USERCONTEXT_COOKIE; +- /* We need to restart since we got a successful URB, but not ours */ +- goto restart; +- } +- +- /* +- * If there was an error, that wasn't EAGAIN (no completion), then +- * something happened during the reaping and we should return that +- * error now +- */ +- if (ret < 0 && !urb.usercontext && errno != EAGAIN) +- USB_ERROR_STR(-errno, "error reaping URB: %s", strerror(errno)); ++ if (ret < 0 || tdout) /* We didn't get a sucessful URB back */ ++ break; + + bytesdone += urb.actual_length; +- } while ((ret == 0 || urb.usercontext) && bytesdone < size && urb.actual_length == requested); +- +- /* If the URB didn't complete in success or error, then let's unlink it */ +- if (ret < 0 && !urb.usercontext) { +- int rc; ++ } while (bytesdone < size && urb.actual_length == requested); + +- if (!waiting) +- rc = -ETIMEDOUT; +- else +- rc = urb.status; +- +- ret = ioctl(dev->fd, IOCTL_USB_DISCARDURB, &urb); +- if (ret < 0 && errno != EINVAL && usb_debug >= 1) +- fprintf(stderr, "error discarding URB: %s", strerror(errno)); +- +- /* +- * When the URB is unlinked, it gets moved to the completed list and +- * then we need to reap it or else the next time we call this function, +- * we'll get the previous completion and exit early +- */ +- ioctl(dev->fd, IOCTL_USB_REAPURB, &context); +- +- return rc; +- } +- +- return bytesdone; ++ if (tdout) ++ rc = -ETIMEDOUT; ++ else if (ret < 0) ++ rc = urb.status; ++ else ++ rc = bytesdone; ++ return rc; + } + + int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, +--- libusb-0.1.12/linux.h 2005-02-02 23:00:07.000000000 +0100 ++++ libusb/linux.h 2008-06-30 15:21:09.000000000 +0200 +@@ -69,7 +69,7 @@ + int number_of_packets; + int error_count; + unsigned int signr; /* signal to be sent on error, -1 if none should be sent */ +- void *usercontext; ++ volatile void *usercontext; + struct usb_iso_packet_desc iso_frame_desc[0]; + }; + +--- libusb-0.1.12/Makefile.am 2006-03-04 03:52:46.000000000 +0100 ++++ libusb/Makefile.am 2008-06-30 15:21:08.000000000 +0200 +@@ -41,7 +41,7 @@ + endif + endif + +-AM_CFLAGS += $(AM_CFLAGS_EXT) ++AM_CFLAGS += $(AM_CFLAGS_EXT) -pthread + + AM_CPPFLAGS = -I. + AM_CXXFLAGS = diff --git a/libusb.spec b/libusb.spec index 297c881..f52f879 100644 --- a/libusb.spec +++ b/libusb.spec @@ -1,12 +1,13 @@ Summary: A library which allows userspace access to USB devices Name: libusb Version: 0.1.12 -Release: 16%{?dist} +Release: 17%{?dist} Source0: http://prdownloads.sourceforge.net/libusb/%{name}-%{version}.tar.gz Patch0: libusb-0.1.12-libusbconfig.patch Patch1: libusb-0.1.12-memset.patch Patch2: libusb-0.1.12-openat.patch Patch3: libusb-0.1.12-wakeups.patch +Patch4: libusb-0.1.12-concurrency-timeout.patch License: LGPLv2+ Group: System Environment/Libraries BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -43,6 +44,7 @@ This package contains static libraries to develop applications that use libusb. %patch1 -p1 -b .memset %patch2 -p1 -b .openat #%patch3 -p0 -b .wakeups +%patch4 -p1 -b .concurrency-timeout %build autoconf @@ -82,6 +84,10 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/*.a %changelog +* Sat Aug 2 2008 Jindrich Novy 0.1.12-17 +- apply patch from Graeme Gill to fix concurrency timeout + handling (#456811) + * Fri Apr 18 2008 Jindrich Novy 0.1.12-16 - rebuild to fix broken ppc build