diff options
author | parafin <parafin@paraf.in> | 2015-10-15 20:12:42 +0300 |
---|---|---|
committer | Nathan Hjelm <hjelmn@me.com> | 2016-03-05 09:11:41 -0700 |
commit | 763668cc925b0f07d5320f2bf8038a9d504dc63d (patch) | |
tree | 874e370e9af22e03238bd7385a918bc59a72f3a2 | |
parent | a499ef20a1e49050c93181d64ba84278aef8bb99 (diff) | |
download | libusb-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>
-rw-r--r-- | libusb/os/darwin_usb.c | 17 | ||||
-rw-r--r-- | libusb/version_nano.h | 2 |
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 |