From 0dcca2c2c85526ea27376f72d703a726a83aa5dd Mon Sep 17 00:00:00 2001 From: Suyeon Hwang Date: Tue, 24 Oct 2023 15:33:44 +0900 Subject: [PATCH] Fix thread suspend logic for pkgmgr_thread - Issue: If pkgmgr_client_new() is continously failed, pkgmgr_thread can sleep very long time and this can cause deadlock when the app tries to destroy the handle. - Solution: To reduce the error log, gradually increased suspend time logic was added in pkgmgr thread. However, the suspend time could increase without limitation and this long suspend time might cause critical deadlock. To solve this problem, this patch changes the suspend logic with conditional variable. Using conditional variable, the framework will be able to resume the thread and properly terminate it even if the suspend time is too long. And also this patch adds a limitation for the suspend time. So, even if the thread termination logic is failed, the thread will be exited in a reasonable time. Change-Id: I6e126464032a70dbf1d5f63a03c7a85c01ef0a8d Signed-off-by: Suyeon Hwang --- client/tts_core.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/client/tts_core.c b/client/tts_core.c index b0e5382..b389d62 100644 --- a/client/tts_core.c +++ b/client/tts_core.c @@ -29,8 +29,6 @@ static const int TTS_ERROR_FAIL_TO_SEND_HELLO = TIZEN_ERROR_TTS | 0xFF; /* Static variables */ -static atomic_bool g_is_thread_canceled = false; - static char* g_engine_name = NULL; static int g_engine_update_status = 0; static atomic_bool g_is_engine_name_changed = false; @@ -42,6 +40,7 @@ static char* g_pkgmgr_status = NULL; static pkgmgr_client* g_pkgmgr = NULL; static Ecore_Thread* g_pkgmgr_thread = NULL; static pthread_mutex_t g_pkgmgr_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t g_pkgmgr_cond = PTHREAD_COND_INITIALIZER; static char* g_language = NULL; static int g_voice_type = -1; @@ -239,13 +238,14 @@ static int __pkgmgr_status_cb(uid_t target_uid, int req_id, const char *type, co static void __create_pkgmgr_thread(void* data, Ecore_Thread* thread) { SLOG(LOG_INFO, TAG_TTSC, "[DEBUG] create pkgmgr thread"); + static const long long MAX_TIME_DELAY = 60000000000ll; + long long time_delay = 10000000ll; + int cnt = 0; pthread_mutex_lock(&g_pkgmgr_mutex); - int time_delay = 10000; - int cnt = 0; while (NULL == g_pkgmgr) { /* Checking the thread is canceled or not */ - if (g_is_thread_canceled) { + if (EINA_TRUE == ecore_thread_check(g_pkgmgr_thread)) { SLOG(LOG_INFO, TAG_TTSC, "[INFO] g_pkgmgr_thread is canceled. Exit"); break; } @@ -278,9 +278,16 @@ static void __create_pkgmgr_thread(void* data, Ecore_Thread* thread) g_pkgmgr = NULL; } - if (0 == cnt % 5) time_delay *= 2; + if (MAX_TIME_DELAY > time_delay && 0 == cnt % 5) time_delay *= 2; + + struct timespec time_sleep; + timespec_get(&time_sleep, TIME_UTC); + time_sleep.tv_nsec += time_delay % 1000000000; + int quotient = time_sleep.tv_nsec / 1000000000; + time_sleep.tv_nsec = time_sleep.tv_nsec % 1000000000; + time_sleep.tv_sec += time_delay / 1000000000 + quotient; - usleep(time_delay); + pthread_cond_timedwait(&g_pkgmgr_cond, &g_pkgmgr_mutex, &time_sleep); cnt++; } pthread_mutex_unlock(&g_pkgmgr_mutex); @@ -291,7 +298,6 @@ static void __create_pkgmgr_thread(void* data, Ecore_Thread* thread) static void __finish_pkgmgr_thread(void* data, Ecore_Thread* thread) { SLOG(LOG_INFO, TAG_TTSC, "[DEBUG] Finish pkgmgr thread"); - g_is_thread_canceled = false; g_pkgmgr_thread = NULL; } @@ -299,7 +305,6 @@ static void __finish_pkgmgr_thread(void* data, Ecore_Thread* thread) static void __cancel_pkgmgr_thread(void* data, Ecore_Thread* thread) { SLOG(LOG_INFO, TAG_TTSC, "[DEBUG] Cancel pkgmgr thread"); - g_is_thread_canceled = false; g_pkgmgr_thread = NULL; } //LCOV_EXCL_STOP @@ -702,7 +707,9 @@ int tts_core_deinitialize() if (NULL != g_reprepare_thread && EINA_FALSE == ecore_thread_check(g_reprepare_thread)) { SLOG(LOG_INFO, TAG_TTSC, "[INFO] Cancel reprepare thread"); ecore_thread_cancel(g_reprepare_thread); - ecore_thread_wait(g_reprepare_thread, 0.5); // wait g_reprepare_thread is terminated. + + ecore_thread_wait(g_reprepare_thread, 1.0); // wait g_reprepare_thread is terminated. + g_reprepare_thread = NULL; } app_manager_unset_app_context_event_cb(); @@ -713,7 +720,14 @@ int tts_core_deinitialize() if (NULL != g_pkgmgr_thread) { SLOG(LOG_INFO, TAG_TTSC, "[INFO] Cancel pkgmgr thread"); - g_is_thread_canceled = true; + ecore_thread_cancel(g_pkgmgr_thread); + + pthread_mutex_lock(&g_pkgmgr_mutex); + pthread_cond_broadcast(&g_pkgmgr_cond); + pthread_mutex_unlock(&g_pkgmgr_mutex); + + ecore_thread_wait(g_pkgmgr_thread, 1.0); // wait g_reprepare_thread is terminated. + g_pkgmgr_thread = NULL; } if (NULL != g_language) { -- 2.7.4