Add intended_destroy flag to destroy only when intended. 13/255913/1
authorJoonbum Ko <joonbum.ko@samsung.com>
Wed, 24 Mar 2021 10:48:31 +0000 (19:48 +0900)
committerJoonbum Ko <joonbum.ko@samsung.com>
Wed, 24 Mar 2021 10:48:34 +0000 (19:48 +0900)
 - G_IO_IN may occur in eventfd of finalizer source due to
  some unexpected errors.
   In this case, if gsource destroyed in unintended,
  a fatal problem may occur in thread.
 - The intended_destroy flag of the newly added to tpl_gsource
  will help the finalizer source to operate normally only if it is
  intended G_IO_IN.

Change-Id: I6dd6a2de7e3c4ff667f8d639e30783584e6e8cec
Signed-off-by: Joonbum Ko <joonbum.ko@samsung.com>
src/tpl_utils_gthread.c

index b024088..47a7041 100644 (file)
@@ -23,10 +23,13 @@ struct _tpl_gsource {
 
        tpl_gsource_type_t     type;
        tpl_gsource           *finalizer;
+       tpl_bool_t             intended_destroy;
 
        void                  *data;
 };
 
+static void
+__gsource_remove_and_destroy(tpl_gsource *source);
 
 static gpointer
 _tpl_gthread_init(gpointer data)
@@ -175,15 +178,14 @@ _thread_source_dispatch(GSource *source, GSourceFunc cb, gpointer data)
                if (gsource->gsource_funcs && gsource->gsource_funcs->dispatch)
                        ret = gsource->gsource_funcs->dispatch(gsource, message);
 
-               if (gsource->type == SOURCE_TYPE_FINALIZER) {
+               if (gsource->type == SOURCE_TYPE_FINALIZER &&
+                       gsource->intended_destroy == TPL_TRUE) {
                        tpl_gsource *del_source = (tpl_gsource *)gsource->data;
                        if (!g_source_is_destroyed(&del_source->gsource)) {
                                tpl_gthread *thread = del_source->thread;
                                g_mutex_lock(&thread->thread_mutex);
 
-                               g_source_remove_unix_fd(&del_source->gsource, del_source->tag);
-                               g_source_destroy(&del_source->gsource);
-                               g_source_unref(&del_source->gsource);
+                               __gsource_remove_and_destroy(del_source);
 
                                g_cond_signal(&thread->thread_cond);
                                g_mutex_unlock(&thread->thread_mutex);
@@ -200,9 +202,7 @@ _thread_source_dispatch(GSource *source, GSourceFunc cb, gpointer data)
 
        if (gsource->type == SOURCE_TYPE_DISPOSABLE ||
                gsource->type == SOURCE_TYPE_FINALIZER) {
-               g_source_remove_unix_fd(&gsource->gsource, gsource->tag);
-               g_source_destroy(&gsource->gsource);
-               g_source_unref(&gsource->gsource);
+               __gsource_remove_and_destroy(gsource);
                ret = G_SOURCE_REMOVE;
        }
 
@@ -265,6 +265,7 @@ tpl_gsource_create(tpl_gthread *thread, void *data, int fd,
        new_gsource->gsource_funcs = funcs;
        new_gsource->data          = data;
        new_gsource->type          = type;
+       new_gsource->intended_destroy = TPL_FALSE;
 
        if (new_gsource->type == SOURCE_TYPE_NORMAL) {
                tpl_gsource *finalizer = tpl_gsource_create(thread, new_gsource, -1,
@@ -285,6 +286,17 @@ tpl_gsource_create(tpl_gthread *thread, void *data, int fd,
        return new_gsource;
 }
 
+static void
+__gsource_remove_and_destroy(tpl_gsource *source)
+{
+       TPL_DEBUG("[GSOURCE_DESTROY] tpl_gsource(%p) type(%d)",
+                         source, source->type);
+
+       g_source_remove_unix_fd(&source->gsource, source->tag);
+       g_source_destroy(&source->gsource);
+       g_source_unref(&source->gsource);
+}
+
 void
 tpl_gsource_destroy(tpl_gsource *source, tpl_bool_t destroy_in_thread)
 {
@@ -294,32 +306,27 @@ tpl_gsource_destroy(tpl_gsource *source, tpl_bool_t destroy_in_thread)
                return;
        }
 
-       TPL_DEBUG("[GSOURCE_DESTROY] tpl_gsource(%p) type(%d)",
-                         source, source->type);
+       if (source->type == SOURCE_TYPE_NORMAL &&
+               source->finalizer) {
+               tpl_gsource *finalizer = source->finalizer;
 
-       if (destroy_in_thread) {
-               tpl_gthread *thread = source->thread;
-               if (source->type == SOURCE_TYPE_NORMAL) {
+               if (destroy_in_thread) {
+                       tpl_gthread *thread = source->thread;
                        g_mutex_lock(&thread->thread_mutex);
 
-                       tpl_gsource_send_message(source->finalizer, 1);
+                       finalizer->intended_destroy = TPL_TRUE;
+                       tpl_gsource_send_message(finalizer, 1);
 
                        g_cond_wait(&thread->thread_cond, &thread->thread_mutex);
                        g_mutex_unlock(&thread->thread_mutex);
-               }
-       } else {
-               if (source->type == SOURCE_TYPE_NORMAL &&
-                       source->finalizer) {
-                       tpl_gsource *finalize = source->finalizer;
-                       g_source_remove_unix_fd(&finalize->gsource, finalize->tag);
-                       g_source_destroy(&finalize->gsource);
-                       g_source_unref(&finalize->gsource);
+               } else {
+                       __gsource_remove_and_destroy(finalizer);
                        source->finalizer = NULL;
                }
+       }
 
-               g_source_remove_unix_fd(&source->gsource, source->tag);
-               g_source_destroy(&source->gsource);
-               g_source_unref(&source->gsource);
+       if (!destroy_in_thread) {
+               __gsource_remove_and_destroy(source);
        }
 }