From 1d9e6e351b51e7401898dde96418c0ee10ad878f Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Thu, 11 Dec 2014 09:20:20 +0100 Subject: Fix overlong blocking in np_client_free() When using ideviceinstaller, np_client_free() would block for several minutes when ideviceinstaller cleans up after installing the application. This happens because the function is blocking on thread_join(), waiting for the notification watcher thread to finish. It only ends when np_get_notification() returns a negative value after getting a timeout, which takes several minutes. However, the thread loop will also exit early if client->parent gets NULL (the loop is iterated every 500ms), so this commit ensures client->parent gets set to NULL early in np_client_free() so that thread_join() does not block for a long time. Signed-off-by: Martin Szulecki --- src/notification_proxy.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/notification_proxy.c b/src/notification_proxy.c index dba42db..4b028f6 100644 --- a/src/notification_proxy.c +++ b/src/notification_proxy.c @@ -114,6 +114,7 @@ LIBIMOBILEDEVICE_API np_error_t np_client_start_service(idevice_t device, np_cli LIBIMOBILEDEVICE_API np_error_t np_client_free(np_client_t client) { plist_t dict; + property_list_service_client_t parent; if (!client) return NP_E_INVALID_ARG; @@ -123,12 +124,16 @@ LIBIMOBILEDEVICE_API np_error_t np_client_free(np_client_t client) property_list_service_send_xml_plist(client->parent, dict); plist_free(dict); + parent = client->parent; + /* notifies the client->notifier thread that it should terminate */ + client->parent = NULL; + if (client->notifier) { debug_info("joining np callback"); thread_join(client->notifier); } else { dict = NULL; - property_list_service_receive_plist(client->parent, &dict); + property_list_service_receive_plist(parent, &dict); if (dict) { #ifndef STRIP_DEBUG_CODE char *cmd_value = NULL; @@ -150,8 +155,7 @@ LIBIMOBILEDEVICE_API np_error_t np_client_free(np_client_t client) } } - property_list_service_client_free(client->parent); - client->parent = NULL; + property_list_service_client_free(parent); mutex_destroy(&client->mutex); free(client); -- cgit v1.1-32-gdbae