diff options
author | Hans de Goede <hdegoede@redhat.com> | 2013-05-16 16:21:23 +0200 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2013-05-16 17:18:32 +0200 |
commit | 6270638991a56489128955699e37d5ca33f30f83 (patch) | |
tree | e02d71bb50a57c688596ca774028258905f59053 | |
parent | 50f79a1ada1df394dfeac4975e37b087a124e321 (diff) | |
download | libusb-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.c | 10 | ||||
-rw-r--r-- | libusb/version_nano.h | 2 |
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 |