summaryrefslogtreecommitdiff
path: root/libusb
diff options
context:
space:
mode:
authorparafin <parafin@paraf.in>2015-10-15 20:12:42 +0300
committerNathan Hjelm <hjelmn@me.com>2016-03-05 09:11:41 -0700
commit763668cc925b0f07d5320f2bf8038a9d504dc63d (patch)
tree874e370e9af22e03238bd7385a918bc59a72f3a2 /libusb
parenta499ef20a1e49050c93181d64ba84278aef8bb99 (diff)
downloadlibusb-763668cc925b0f07d5320f2bf8038a9d504dc63d.tar.gz
darwin: fix occasional dead-lock on libusb_exit
CFRunLoopStop() isn't thread-safe, see for example this bugreport: https://github.com/joyent/libuv/issues/799 Use CFRunLoopSource instead Closes #112 Signed-off-by: Nathan Hjelm <hjelmn@me.com>
Diffstat (limited to 'libusb')
-rw-r--r--libusb/os/darwin_usb.c17
-rw-r--r--libusb/version_nano.h2
2 files changed, 17 insertions, 2 deletions
diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c
index 0f346f5..4e4ab04 100644
--- a/libusb/os/darwin_usb.c
+++ b/libusb/os/darwin_usb.c
@@ -54,6 +54,7 @@ static clock_serv_t clock_realtime;
static clock_serv_t clock_monotonic;
static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */
+static CFRunLoopSourceRef libusb_darwin_acfls = NULL; /* shutdown signal for event cf loop */
static volatile int32_t initCount = 0;
static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -383,6 +384,7 @@ static void *darwin_event_thread_main (void *arg0) {
#endif
/* hotplug (device arrival/removal) sources */
+ CFRunLoopSourceContext libusb_shutdown_cfsourcectx;
CFRunLoopSourceRef libusb_notification_cfsource;
io_notification_port_t libusb_notification_port;
io_iterator_t libusb_rem_device_iterator;
@@ -393,6 +395,13 @@ static void *darwin_event_thread_main (void *arg0) {
runloop = CFRunLoopGetCurrent ();
CFRetain (runloop);
+ /* add the shutdown cfsource to the run loop */
+ memset(&libusb_shutdown_cfsourcectx, 0, sizeof(libusb_shutdown_cfsourcectx));
+ libusb_shutdown_cfsourcectx.info = runloop;
+ libusb_shutdown_cfsourcectx.perform = (void (*)(void *))CFRunLoopStop;
+ libusb_darwin_acfls = CFRunLoopSourceCreate(NULL, 0, &libusb_shutdown_cfsourcectx);
+ CFRunLoopAddSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode);
+
/* add the notification port to the run loop */
libusb_notification_port = IONotificationPortCreate (kIOMasterPortDefault);
libusb_notification_cfsource = IONotificationPortGetRunLoopSource (libusb_notification_port);
@@ -442,6 +451,9 @@ static void *darwin_event_thread_main (void *arg0) {
/* remove the notification cfsource */
CFRunLoopRemoveSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode);
+ /* remove the shutdown cfsource */
+ CFRunLoopRemoveSource(runloop, libusb_darwin_acfls, kCFRunLoopDefaultMode);
+
/* delete notification port */
IONotificationPortDestroy (libusb_notification_port);
@@ -449,8 +461,10 @@ static void *darwin_event_thread_main (void *arg0) {
IOObjectRelease (libusb_rem_device_iterator);
IOObjectRelease (libusb_add_device_iterator);
+ CFRelease (libusb_darwin_acfls);
CFRelease (runloop);
+ libusb_darwin_acfls = NULL;
libusb_darwin_acfl = NULL;
pthread_exit (NULL);
@@ -522,7 +536,8 @@ static void darwin_exit (void) {
mach_port_deallocate(mach_task_self(), clock_monotonic);
/* stop the event runloop and wait for the thread to terminate. */
- CFRunLoopStop (libusb_darwin_acfl);
+ CFRunLoopSourceSignal(libusb_darwin_acfls);
+ CFRunLoopWakeUp (libusb_darwin_acfl);
pthread_join (libusb_darwin_at, NULL);
}
}
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 5709b65..039b1d1 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11091
+#define LIBUSB_NANO 11093