From 0c7e2e12f5157c17d91e57ed9c3c7f92569d2ee8 Mon Sep 17 00:00:00 2001 From: "wn.jang" Date: Wed, 27 Nov 2019 16:37:28 +0900 Subject: [PATCH] Fix thread unsafety issue Change-Id: I11525ef74b89518ba16c44e1d0ad111c9aa51be9 --- client/vc_widget.c | 76 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/client/vc_widget.c b/client/vc_widget.c index 89faa97..c6dcd8a 100644 --- a/client/vc_widget.c +++ b/client/vc_widget.c @@ -41,9 +41,15 @@ static Ecore_Timer* g_w_notify_result_timer = NULL; static pthread_mutex_t g_w_init_mutex = PTHREAD_MUTEX_INITIALIZER; +typedef enum { + VC_PREPARE_THREAD_NONE = 0, + VC_PREPARE_THREAD_REQUESTED = 1, + VC_PREPARE_THREAD_STARTED = 2, + VC_PREPARE_THREAD_ENDED = VC_PREPARE_THREAD_NONE +} vc_prepare_thread_status_e; + static Ecore_Thread* g_w_prepare_thread = NULL; static bool g_ask_to_cancel_preparing = false; -static bool g_is_prepare_thread_alive = false; static int g_daemon_pid = 0; @@ -242,6 +248,31 @@ static void __vc_widget_delete_timer() return; } + +static int _vc_widget_wait_to_end_thread(void) +{ + int count = 0; + SLOG(LOG_WARN, TAG_VCW, "[Widget] prepare_thread info(%p)", g_w_prepare_thread); + if (g_w_prepare_thread) { + g_ask_to_cancel_preparing = true; + SLOG(LOG_WARN, TAG_VCW, "[WARNING] The cancel preparing_thread is asked"); + } + + while (g_w_prepare_thread) { + usleep(50000); + + if (100 == count) { + SLOG(LOG_WARN, TAG_VCW, "[WARNING!!] Thread is blocked, cnt(%d)", count); + break; + } else if (0 != count && 0 == count % 5) { + SLOG(LOG_WARN, TAG_VCW, "[WARNING!!] Thread is alive, cnt(%d)", count); + } + count++; + } + SLOG(LOG_WARN, TAG_VCW, "[Widget] prepare_thread is terminated"); + return 0; +} + int vc_widget_deinitialize(vc_h vc_w) { SLOG(LOG_DEBUG, TAG_VCW, "@@@ [Widget] Deinitialize"); @@ -261,6 +292,9 @@ int vc_widget_deinitialize(vc_h vc_w) g_ask_to_cancel_preparing = true; + /* Wait for ending thread */ + _vc_widget_wait_to_end_thread(); + vc_state_e state; vc_widget_client_get_state(vc_w, &state); vc_widget_s* widget = widget_get(vc_w); @@ -484,22 +518,20 @@ static void __start_prepare_thread(void *data, Ecore_Thread *thread) SLOG(LOG_INFO, TAG_VCW, "@@@ Start prepare thread"); int ret = -1, retry_count = 0; vc_h vc_w = (vc_h)data; - g_is_prepare_thread_alive = true; /* Send hello */ while (0 != ret) { if (g_ask_to_cancel_preparing) { SLOG(LOG_WARN, TAG_VCW, "[WARNING] Thread is canceled."); - __vc_widget_internal_unprepare(vc_w); ecore_main_loop_thread_safe_call_async(__vc_widget_delete_focus_event_handler, NULL); - g_is_prepare_thread_alive = false; + g_w_prepare_thread = NULL; return; } if (retry_count == 30) { SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to request hello !!"); ecore_main_loop_thread_safe_call_async(__vc_widget_delete_focus_event_handler, NULL); - g_is_prepare_thread_alive = false; + g_w_prepare_thread = NULL; return; } @@ -517,17 +549,15 @@ static void __start_prepare_thread(void *data, Ecore_Thread *thread) while (0 != ret) { if (g_ask_to_cancel_preparing) { SLOG(LOG_WARN, TAG_VCW, "[WARNING] Thread is canceled."); - __vc_widget_internal_unprepare(vc_w); ecore_main_loop_thread_safe_call_async(__vc_widget_delete_focus_event_handler, NULL); - g_is_prepare_thread_alive = false; + g_w_prepare_thread = NULL; return; } if (retry_count == 10) { SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to connect daemon !!"); - __vc_widget_internal_unprepare(vc_w); ecore_main_loop_thread_safe_call_async(__vc_widget_delete_focus_event_handler, NULL); - g_is_prepare_thread_alive = false; + g_w_prepare_thread = NULL; return; } ret = __vc_widget_connect_daemon((void*)vc_w); @@ -537,21 +567,19 @@ static void __start_prepare_thread(void *data, Ecore_Thread *thread) retry_count++; } + g_w_prepare_thread = NULL; SLOG(LOG_DEBUG, TAG_VCW, "@@@"); - g_is_prepare_thread_alive = false; return; } static void __end_prepare_thread(void *data, Ecore_Thread *thread) { SLOG(LOG_DEBUG, TAG_VCW, "@@@ End prepare thread"); - g_w_prepare_thread = NULL; } static void __cancel_prepare_thread(void *data, Ecore_Thread *thread) { SLOG(LOG_DEBUG, TAG_VCW, "@@@ Cancel prepare thread"); - g_w_prepare_thread = NULL; } int vc_widget_prepare(vc_h vc_w) @@ -592,7 +620,7 @@ int vc_widget_prepare(vc_h vc_w) __vc_widget_add_focus_event_handler(NULL); // Check ecore thread - if (g_w_prepare_thread && !ecore_thread_check(g_w_prepare_thread)) { + if (g_w_prepare_thread) { SLOG(LOG_INFO, TAG_VCW, "[INFO] prepare_thread is already runnning"); pthread_mutex_unlock(&g_w_init_mutex); return VC_ERROR_NONE; @@ -615,26 +643,12 @@ int vc_widget_unprepare(vc_h vc_w) } pthread_mutex_lock(&g_w_init_mutex); - int count = 0; - SLOG(LOG_WARN, TAG_VCW, "[Widget] prepare_thread info(%p), check(%d)", g_w_prepare_thread, ecore_thread_check(g_w_prepare_thread)); - if (g_w_prepare_thread && !ecore_thread_check(g_w_prepare_thread)) { - bool ret = ecore_thread_cancel(g_w_prepare_thread); - g_ask_to_cancel_preparing = true; - SLOG(LOG_WARN, TAG_VCW, "[WARNING] Thread is alive. The cancel_thread is called, ret(%d)", ret); - } - while (g_is_prepare_thread_alive) { - usleep(50000); + /* Ask to cancel preparing thread */ + g_ask_to_cancel_preparing = true; - if (100 == count) { - SLOG(LOG_WARN, TAG_VCW, "[WARNING!!] Thread is blocked, cnt(%d)", count); - break; - } else if (0 != count && 0 == count % 5) { - SLOG(LOG_WARN, TAG_VCW, "[WARNING!!] Thread is alive, cnt(%d)", count); - } - count++; - } - SLOG(LOG_WARN, TAG_VCW, "[Widget] prepare_thread is terminated"); + /* Wait for ending thread */ + _vc_widget_wait_to_end_thread(); vc_state_e state; if (0 != vc_widget_client_get_state(vc_w, &state)) { -- 2.7.4