Fix thread unsafety issue 07/218707/2
authorwn.jang <wn.jang@samsung.com>
Wed, 27 Nov 2019 07:37:28 +0000 (16:37 +0900)
committerwn.jang <wn.jang@samsung.com>
Wed, 27 Nov 2019 11:40:33 +0000 (20:40 +0900)
Change-Id: I11525ef74b89518ba16c44e1d0ad111c9aa51be9

client/vc_widget.c

index 89faa97..c6dcd8a 100644 (file)
@@ -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)) {