From: wn.jang Date: Fri, 24 May 2019 07:07:23 +0000 (+0900) Subject: Fix thread unsafety issue when preparing X-Git-Tag: submit/tizen/20190524.110156^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=18fe532983f2d66d0c8842c60ee6429694abe87b;p=platform%2Fcore%2Fuifw%2Fvoice-control.git Fix thread unsafety issue when preparing Change-Id: Idafff2ce66490ceade64919f37ad1918ad9be899 --- diff --git a/client/vc_widget.c b/client/vc_widget.c index fafdda2..c185aba 100644 --- a/client/vc_widget.c +++ b/client/vc_widget.c @@ -42,7 +42,8 @@ static Ecore_Timer* g_w_notify_result_timer = NULL; static pthread_mutex_t g_w_init_mutex = PTHREAD_MUTEX_INITIALIZER; static Ecore_Thread* g_w_prepare_thread = NULL; -static int g_w_prepare_canceled = 0; +static bool g_ask_to_cancel_preparing = false; +static bool g_is_prepare_thread_alive = false; static int g_daemon_pid = 0; @@ -269,7 +270,7 @@ int vc_widget_deinitialize(vc_h vc_w) return VC_ERROR_INVALID_STATE; } - g_w_prepare_canceled = 1; + g_ask_to_cancel_preparing = true; vc_state_e state; vc_widget_client_get_state(vc_w, &state); @@ -476,17 +477,22 @@ 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_w_prepare_canceled) { + 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; 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; return; } @@ -502,14 +508,19 @@ static void __start_prepare_thread(void *data, Ecore_Thread *thread) ret = -1; retry_count = 0; while (0 != ret) { - if (g_w_prepare_canceled) { + 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; 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; return; } ret = __vc_widget_connect_daemon((void*)vc_w); @@ -520,21 +531,20 @@ static void __start_prepare_thread(void *data, Ecore_Thread *thread) } SLOG(LOG_DEBUG, TAG_VCW, "@@@"); - + g_is_prepare_thread_alive = false; return; } static void __end_prepare_thread(void *data, Ecore_Thread *thread) { - g_w_prepare_thread = NULL; 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; - g_w_prepare_canceled = 1; } int vc_widget_prepare(vc_h vc_w) @@ -546,10 +556,12 @@ int vc_widget_prepare(vc_h vc_w) return VC_ERROR_NONE; } + pthread_mutex_lock(&g_w_init_mutex); vc_state_e state; if (0 != vc_widget_client_get_state(vc_w, &state)) { SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); SLOG(LOG_DEBUG, TAG_VCW, "@@@"); + pthread_mutex_unlock(&g_w_init_mutex); return VC_ERROR_INVALID_STATE; } @@ -557,6 +569,7 @@ int vc_widget_prepare(vc_h vc_w) if (state != VC_STATE_INITIALIZED) { SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'Initialized'"); SLOG(LOG_DEBUG, TAG_VCW, "@@@"); + pthread_mutex_unlock(&g_w_init_mutex); return VC_ERROR_INVALID_STATE; } @@ -564,6 +577,7 @@ int vc_widget_prepare(vc_h vc_w) if (NULL == widget) { SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to get widget handle"); SLOG(LOG_DEBUG, TAG_VCW, "@@@"); + pthread_mutex_unlock(&g_w_init_mutex); return VC_ERROR_INVALID_STATE; } @@ -572,14 +586,15 @@ int vc_widget_prepare(vc_h vc_w) // Check ecore thread if (g_w_prepare_thread && !ecore_thread_check(g_w_prepare_thread)) { - ecore_thread_cancel(g_w_prepare_thread); - g_w_prepare_thread = NULL; + SLOG(LOG_INFO, TAG_VCW, "[INFO] prepare_thread is already runnning"); + pthread_mutex_unlock(&g_w_init_mutex); + return VC_ERROR_NONE; } - g_w_prepare_canceled = 0; + g_ask_to_cancel_preparing = false; g_w_prepare_thread = ecore_thread_run(__start_prepare_thread, __end_prepare_thread, __cancel_prepare_thread, (void*)vc_w); SLOG(LOG_DEBUG, TAG_VCW, "@@@"); - + pthread_mutex_unlock(&g_w_init_mutex); return VC_ERROR_NONE; } @@ -592,36 +607,33 @@ int vc_widget_unprepare(vc_h vc_w) return VC_ERROR_NONE; } - int prev_thread_count = ecore_thread_active_get(); - int curr_thread_count = prev_thread_count; + pthread_mutex_lock(&g_w_init_mutex); int count = 0; - SLOG(LOG_INFO, TAG_VCW, "[Widget] Current thread count(%d)", curr_thread_count); - + 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)) { - SLOG(LOG_WARN, TAG_VCW, "[WARNING] Thread is alive. Call cancel thread."); - ecore_thread_cancel(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); } - SLOG(LOG_WARN, TAG_VCW, "[Widget] thread info %d %d %d", curr_thread_count, prev_thread_count - curr_thread_count, !ecore_thread_check(g_w_prepare_thread)); - SLOG(LOG_WARN, TAG_VCW, "[Widget] thread count %d", count); - while (0 < curr_thread_count && 1 != prev_thread_count - curr_thread_count && !ecore_thread_check(g_w_prepare_thread)) { + while (g_is_prepare_thread_alive) { usleep(50000); if (100 == count) { - SLOG(LOG_WARN, TAG_VCW, "[WARNING!!] Thread is blocked, cnt(%d), thread count(%d)", count, curr_thread_count); + SLOG(LOG_WARN, TAG_VCW, "[WARNING!!] Thread is blocked, cnt(%d)", count); break; - } else if (0 == count % 5) { - SLOG(LOG_WARN, TAG_VCW, "[WARNING!!] Thread is alive, cnt(%d), thread count(%d)", count, curr_thread_count); + } else if (0 != count && 0 == count % 5) { + SLOG(LOG_WARN, TAG_VCW, "[WARNING!!] Thread is alive, cnt(%d)", count); } count++; - curr_thread_count = ecore_thread_active_get(); } - g_w_prepare_thread = NULL; + SLOG(LOG_WARN, TAG_VCW, "[Widget] prepare_thread is terminated"); vc_state_e state; if (0 != vc_widget_client_get_state(vc_w, &state)) { SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); SLOG(LOG_DEBUG, TAG_VCW, "@@@"); + pthread_mutex_unlock(&g_w_init_mutex); return VC_ERROR_INVALID_STATE; } @@ -629,6 +641,7 @@ int vc_widget_unprepare(vc_h vc_w) if (state != VC_STATE_READY) { SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'READY', state(%d)", state); SLOG(LOG_DEBUG, TAG_VCW, "@@@"); + pthread_mutex_unlock(&g_w_init_mutex); return VC_ERROR_INVALID_STATE; } @@ -638,7 +651,7 @@ int vc_widget_unprepare(vc_h vc_w) g_w_notify_state_timer = ecore_timer_add(0, __vc_widget_notify_state_changed, vc_w); SLOG(LOG_DEBUG, TAG_VCW, "@@@"); - + pthread_mutex_unlock(&g_w_init_mutex); return VC_ERROR_NONE; } diff --git a/server/vcd_server.c b/server/vcd_server.c index 41deae9..e74003f 100644 --- a/server/vcd_server.c +++ b/server/vcd_server.c @@ -1439,6 +1439,10 @@ Eina_Bool vcd_cleanup_client_all(void *data) __vcd_cleanup_client(VCD_CLIENT_TYPE_WIDGET); __vcd_cleanup_client(VCD_CLIENT_TYPE_MANAGER); + if (0 == vcd_client_get_ref_count()) { + SLOG(LOG_DEBUG, TAG_VCD, "[Server] Connected client list is empty"); + ecore_timer_add(0, __finalize_quit_ecore_loop, NULL); + } #if 0 if (0 == vcd_client_get_list(&client_list, &client_count)) { SLOG(LOG_DEBUG, TAG_VCD, "@@@ Clean up client "); @@ -2849,6 +2853,11 @@ int vcd_server_widget_finalize(int pid) /* check if pid is valid */ if (false == vcd_client_widget_is_available(pid)) { SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] pid is NOT valid "); + if (0 == vcd_client_get_ref_count()) { + SLOG(LOG_ERROR, TAG_VCD, "[Server] connected client list is empty, vc-service will be terminated"); + ecore_timer_add(0, __finalize_quit_ecore_loop, NULL); + return 0; + } return VCD_ERROR_INVALID_PARAMETER; } @@ -2858,7 +2867,7 @@ int vcd_server_widget_finalize(int pid) } if (0 == vcd_client_get_ref_count()) { - SLOG(LOG_ERROR, TAG_VCD, "[Server] connected client list is empty"); + SLOG(LOG_ERROR, TAG_VCD, "[Server] connected client list is empty, vc-service will be terminated"); ecore_timer_add(0, __finalize_quit_ecore_loop, NULL); return 0; }