Fix a bug about using condition variables
authorHwankyu Jhun <h.jhun@samsung.com>
Thu, 29 Apr 2021 04:11:00 +0000 (13:11 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Thu, 29 Apr 2021 05:05:16 +0000 (14:05 +0900)
When using condition variables, it's possible that a spurious wakeup may
occur. g_cond_wait() MUST always be used in a loop.

Change-Id: I5bfe6435a601e442c06612a17aed9a7f5daa538a
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
src/aul_worker.c

index c39049e..d76ae2d 100644 (file)
@@ -269,6 +269,12 @@ void aul_worker_destroy(aul_worker_h handle)
                g_thread_join(worker->thread);
        }
 
+       if (worker->loop)
+               g_main_loop_unref(worker->loop);
+
+       if (worker->context)
+               g_main_context_unref(worker->context);
+
        g_cond_clear(&worker->cond);
        g_mutex_clear(&worker->mutex);
 
@@ -306,40 +312,21 @@ static gpointer __worker_thread_loop(gpointer data)
                return NULL;
        }
 
-       worker->context = g_main_context_new();
-       if (!worker->context) {
-               _E("Failed to create GMainContext");
-               g_source_unref(source);
-               g_cond_signal(&worker->cond);
-               g_mutex_unlock(&worker->mutex);
-               return NULL;
-       }
-
-       _W("GMainContext(%p)", worker->context);
        g_source_set_callback(source, (GSourceFunc)__notify_cb, worker, NULL);
        g_source_set_priority(source, G_PRIORITY_HIGH);
        g_source_attach(source, worker->context);
        g_source_unref(source);
 
-       worker->loop = g_main_loop_new(worker->context, FALSE);
        g_main_context_push_thread_default(worker->context);
        g_mutex_unlock(&worker->mutex);
-
-       if (!worker->loop) {
-               _E("Failed to create GMainLoop");
-               goto end;
-       }
-
        g_main_loop_run(worker->loop);
-end:
+
        g_mutex_lock(&worker->mutex);
        if (anr_timer->tag)
                g_source_remove(anr_timer->tag);
 
        g_list_free_full(worker->jobs, __destroy_job);
        g_main_context_pop_thread_default(worker->context);
-       g_main_loop_unref(worker->loop);
-       g_main_context_unref(worker->context);
        g_cond_signal(&worker->cond);
        g_mutex_unlock(&worker->mutex);
        _W("Shut down worker");
@@ -379,6 +366,21 @@ aul_worker_h aul_worker_create(const char *name)
                return NULL;
        }
 
+       worker->context = g_main_context_new();
+       if (!worker->context) {
+               _E("Failed to create GMainContext");
+               aul_worker_destroy(worker);
+               return NULL;
+       }
+       _W("GMainContext(%p)", worker->context);
+
+       worker->loop = g_main_loop_new(worker->context, FALSE);
+       if (!worker->loop) {
+               _E("Failed to create GMainLoop");
+               aul_worker_destroy(worker);
+               return NULL;
+       }
+
        g_mutex_lock(&worker->mutex);
 
        worker->thread = g_thread_new(name, __worker_thread_loop, worker);
@@ -388,7 +390,9 @@ aul_worker_h aul_worker_create(const char *name)
                return NULL;
        }
 
-       g_cond_wait(&worker->cond, &worker->mutex);
+       while (!g_main_loop_is_running(worker->loop))
+               g_cond_wait(&worker->cond, &worker->mutex);
+
        g_mutex_unlock(&worker->mutex);
 
        return worker;