summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2013-05-16 16:21:23 +0200
committerHans de Goede <hdegoede@redhat.com>2013-05-16 17:18:32 +0200
commit6270638991a56489128955699e37d5ca33f30f83 (patch)
treee02d71bb50a57c688596ca774028258905f59053
parent50f79a1ada1df394dfeac4975e37b087a124e321 (diff)
downloadlibusb-6270638991a56489128955699e37d5ca33f30f83.tar.gz
linux: Take hotplug_lock for scan_devices, hotplug_enumerate and _disconnect
As soon as we've started listening for hp events, hotplug_enumerate and _disconnect can run, they do test then add / remove operations on the device list. This can race with scan_devices adding devices, so take the lock around all 3 to avoid the race. Also fix the lock not being released in case of linux_start_event_monitor failure. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--libusb/os/linux_usbfs.c10
-rw-r--r--libusb/version_nano.h2
2 files changed, 8 insertions, 4 deletions
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 3ff5a9a..6a22f7d 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -432,18 +432,18 @@ static int op_init(struct libusb_context *ctx)
}
pthread_mutex_lock(&hotplug_lock);
+ r = LIBUSB_SUCCESS;
if (!init_count++) {
/* start up hotplug event handler */
r = linux_start_event_monitor();
if (LIBUSB_SUCCESS != r) {
usbi_err(ctx, "error starting hotplug event monitor");
- return r;
}
}
+ if (r == LIBUSB_SUCCESS)
+ r = linux_scan_devices(ctx);
pthread_mutex_unlock(&hotplug_lock);
- r = linux_scan_devices(ctx);
-
return r;
}
@@ -1184,6 +1184,7 @@ void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_na
{
struct libusb_context *ctx;
+ pthread_mutex_lock(&hotplug_lock);
list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
if (usbi_get_device_by_session_id(ctx, busnum << 8 | devaddr)) {
/* device already exists in the context */
@@ -1193,6 +1194,7 @@ void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_na
linux_enumerate_device(ctx, busnum, devaddr, sys_name);
}
+ pthread_mutex_unlock(&hotplug_lock);
}
void linux_hotplug_disconnected(uint8_t busnum, uint8_t devaddr, const char *sys_name)
@@ -1200,6 +1202,7 @@ void linux_hotplug_disconnected(uint8_t busnum, uint8_t devaddr, const char *sys
struct libusb_context *ctx;
struct libusb_device *dev;
+ pthread_mutex_lock(&hotplug_lock);
list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
dev = usbi_get_device_by_session_id (ctx, busnum << 8 | devaddr);
if (NULL != dev) {
@@ -1208,6 +1211,7 @@ void linux_hotplug_disconnected(uint8_t busnum, uint8_t devaddr, const char *sys
usbi_err(ctx, "device not found for session %x", busnum << 8 | devaddr);
}
}
+ pthread_mutex_unlock(&hotplug_lock);
}
#if !defined(USE_UDEV)
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index ddcceda..fce37d3 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 10675
+#define LIBUSB_NANO 10676