summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2021-06-20 02:45:09 +0200
committerGravatar Nikias Bassen2021-06-20 02:45:09 +0200
commit5718dd2ae149f615191552eef40f8f90e60a3455 (patch)
treeb6523e8d4a08b04445aa51eec864c255797e3a0c
parentcb50087482cf5a4239ad9c96b7157c45eac12876 (diff)
downloadlibirecovery-5718dd2ae149f615191552eef40f8f90e60a3455.tar.gz
libirecovery-5718dd2ae149f615191552eef40f8f90e60a3455.tar.bz2
Make sure the device event handler thread has started before returning from irecv_device_event_subscribe()
This fixes a potential deadlock that might occur when irecv_device_event_unsubscribe() is called before the device event handler thread has started, eventually resulting in a deadlock.
-rw-r--r--src/libirecovery.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/src/libirecovery.c b/src/libirecovery.c
index 84f0b32..39f6f88 100644
--- a/src/libirecovery.c
+++ b/src/libirecovery.c
@@ -2127,11 +2127,22 @@ static int _irecv_usb_hotplug_cb(libusb_context *ctx, libusb_device *device, lib
2127#endif /* !HAVE_IOKIT */ 2127#endif /* !HAVE_IOKIT */
2128#endif /* !WIN32 */ 2128#endif /* !WIN32 */
2129 2129
2130static void *_irecv_event_handler(void* unused) 2130struct _irecv_event_handler_info {
2131 cond_t startup_cond;
2132 mutex_t startup_mutex;
2133};
2134
2135static void *_irecv_event_handler(void* data)
2131{ 2136{
2137 struct _irecv_event_handler_info* info = (struct _irecv_event_handler_info*)data;
2132#ifdef WIN32 2138#ifdef WIN32
2133 const GUID *guids[] = { &GUID_DEVINTERFACE_DFU, &GUID_DEVINTERFACE_IBOOT, NULL }; 2139 const GUID *guids[] = { &GUID_DEVINTERFACE_DFU, &GUID_DEVINTERFACE_IBOOT, NULL };
2134 int running = 1; 2140 int running = 1;
2141
2142 mutex_lock(&(info->startup_mutex));
2143 cond_signal(&(info->startup_cond));
2144 mutex_unlock(&(info->startup_mutex));
2145
2135 do { 2146 do {
2136 SP_DEVICE_INTERFACE_DATA currentInterface; 2147 SP_DEVICE_INTERFACE_DATA currentInterface;
2137 HDEVINFO usbDevices; 2148 HDEVINFO usbDevices;
@@ -2246,6 +2257,10 @@ static void *_irecv_event_handler(void* unused)
2246 i++; 2257 i++;
2247 } 2258 }
2248 2259
2260 mutex_lock(&(info->startup_mutex));
2261 cond_signal(&(info->startup_cond));
2262 mutex_unlock(&(info->startup_mutex));
2263
2249 CFRunLoopRun(); 2264 CFRunLoopRun();
2250 2265
2251#else /* !HAVE_IOKIT */ 2266#else /* !HAVE_IOKIT */
@@ -2253,6 +2268,11 @@ static void *_irecv_event_handler(void* unused)
2253 static libusb_hotplug_callback_handle usb_hotplug_cb_handle; 2268 static libusb_hotplug_callback_handle usb_hotplug_cb_handle;
2254 libusb_hotplug_register_callback(irecv_hotplug_ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_ENUMERATE, APPLE_VENDOR_ID, LIBUSB_HOTPLUG_MATCH_ANY, 0, _irecv_usb_hotplug_cb, NULL, &usb_hotplug_cb_handle); 2269 libusb_hotplug_register_callback(irecv_hotplug_ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_ENUMERATE, APPLE_VENDOR_ID, LIBUSB_HOTPLUG_MATCH_ANY, 0, _irecv_usb_hotplug_cb, NULL, &usb_hotplug_cb_handle);
2255 int running = 1; 2270 int running = 1;
2271
2272 mutex_lock(&(info->startup_mutex));
2273 cond_signal(&(info->startup_cond));
2274 mutex_unlock(&(info->startup_mutex));
2275
2256 do { 2276 do {
2257 struct timeval tv; 2277 struct timeval tv;
2258 tv.tv_sec = tv.tv_usec = 0; 2278 tv.tv_sec = tv.tv_usec = 0;
@@ -2272,6 +2292,10 @@ static void *_irecv_event_handler(void* unused)
2272 libusb_device **devs; 2292 libusb_device **devs;
2273 int running = 1; 2293 int running = 1;
2274 2294
2295 mutex_lock(&(info->startup_mutex));
2296 cond_signal(&(info->startup_cond));
2297 mutex_unlock(&(info->startup_mutex));
2298
2275 do { 2299 do {
2276 cnt = libusb_get_device_list(irecv_hotplug_ctx, &devs); 2300 cnt = libusb_get_device_list(irecv_hotplug_ctx, &devs);
2277 if (cnt < 0) { 2301 if (cnt < 0) {
@@ -2349,6 +2373,9 @@ IRECV_API irecv_error_t irecv_device_event_subscribe(irecv_device_event_context_
2349 mutex_unlock(&listener_mutex); 2373 mutex_unlock(&listener_mutex);
2350 2374
2351 if (th_event_handler == THREAD_T_NULL || !thread_alive(th_event_handler)) { 2375 if (th_event_handler == THREAD_T_NULL || !thread_alive(th_event_handler)) {
2376 struct _irecv_event_handler_info info;
2377 cond_init(&info.startup_cond);
2378 mutex_init(&info.startup_mutex);
2352#ifndef WIN32 2379#ifndef WIN32
2353#ifndef HAVE_IOKIT 2380#ifndef HAVE_IOKIT
2354 libusb_init(&irecv_hotplug_ctx); 2381 libusb_init(&irecv_hotplug_ctx);
@@ -2356,7 +2383,13 @@ IRECV_API irecv_error_t irecv_device_event_subscribe(irecv_device_event_context_
2356#endif 2383#endif
2357 collection_init(&devices); 2384 collection_init(&devices);
2358 mutex_init(&device_mutex); 2385 mutex_init(&device_mutex);
2359 thread_new(&th_event_handler, _irecv_event_handler, NULL); 2386 mutex_lock(&info.startup_mutex);
2387 if (thread_new(&th_event_handler, _irecv_event_handler, &info) == 0) {
2388 cond_wait(&info.startup_cond, &info.startup_mutex);
2389 }
2390 mutex_unlock(&info.startup_mutex);
2391 cond_destroy(&info.startup_cond);
2392 mutex_destroy(&info.startup_mutex);
2360 } 2393 }
2361 2394
2362 *context = _context; 2395 *context = _context;
@@ -2378,10 +2411,11 @@ IRECV_API irecv_error_t irecv_device_event_unsubscribe(irecv_device_event_contex
2378 int num = collection_count(&listeners); 2411 int num = collection_count(&listeners);
2379 mutex_unlock(&listener_mutex); 2412 mutex_unlock(&listener_mutex);
2380 2413
2381 if (num == 0) { 2414 if (num == 0 && th_event_handler != THREAD_T_NULL && thread_alive(th_event_handler)) {
2382#ifdef HAVE_IOKIT 2415#ifdef HAVE_IOKIT
2383 if (iokit_runloop) { 2416 if (iokit_runloop) {
2384 CFRunLoopStop(iokit_runloop); 2417 CFRunLoopStop(iokit_runloop);
2418 iokit_runloop = NULL;
2385 } 2419 }
2386#endif 2420#endif
2387 thread_join(th_event_handler); 2421 thread_join(th_event_handler);