summaryrefslogtreecommitdiff
path: root/libusb/sync.c
diff options
context:
space:
mode:
authorGraeme Gill <graeme2@argyllcms.com>2011-09-10 15:47:05 +0200
committerPeter Stuge <peter@stuge.se>2011-09-22 11:25:29 +0200
commit6696512aade99bb15d6792af90ae329af270eba6 (patch)
tree9137a1fdd3b78ace9d6b49902054598b57e1b3e7 /libusb/sync.c
parentcfee5446cdb2974c1e90c7c379a365c495975aef (diff)
downloadlibusb-6696512aade99bb15d6792af90ae329af270eba6.tar.gz
Fix #56 race condition causing delayed completion of sync transfers
The sync API had a race where it would check a condition to know if it needed to call a libusb_handle_events() function. However, the check was done outside of the lock that is held while the condition is set, so another thread could completely serve whatever was needed to make the condition true between it being checked and the event handler being called. This situation would be detected after a libusb-internal timeout of 60 seconds, after which the transfer would be completed without error, but with significant delay. Original patch at http://marc.info/?l=libusb-devel&m=127252114815709 Changes by Hans de Goede: - Renamed the "race-proof" functions from libusb_handle_events*_check() to libusb_handle_events*_completed() - Drop r = 0 setting in libusb_handle_events_timeout_completed() (to make both completed checking cases identical flow wise) Signed-off-by: Hans de Goede <hdegoede@redhat.com> [stuge: Simplify libusb_handle_events_timeout() change with a goto] [pbatard: Fix _handle_events_timeout() and _completed() definitions]
Diffstat (limited to 'libusb/sync.c')
-rw-r--r--libusb/sync.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/libusb/sync.c b/libusb/sync.c
index 3870f95..d50413b 100644
--- a/libusb/sync.c
+++ b/libusb/sync.c
@@ -102,13 +102,13 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle,
}
while (!completed) {
- r = libusb_handle_events(HANDLE_CTX(dev_handle));
+ r = libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed);
if (r < 0) {
if (r == LIBUSB_ERROR_INTERRUPTED)
continue;
libusb_cancel_transfer(transfer);
while (!completed)
- if (libusb_handle_events(HANDLE_CTX(dev_handle)) < 0)
+ if (libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed) < 0)
break;
libusb_free_transfer(transfer);
return r;
@@ -172,13 +172,13 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle,
}
while (!completed) {
- r = libusb_handle_events(HANDLE_CTX(dev_handle));
+ r = libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed);
if (r < 0) {
if (r == LIBUSB_ERROR_INTERRUPTED)
continue;
libusb_cancel_transfer(transfer);
while (!completed)
- if (libusb_handle_events(HANDLE_CTX(dev_handle)) < 0)
+ if (libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed) < 0)
break;
libusb_free_transfer(transfer);
return r;