Added argument to function tpl_gsource_destroy 71/254771/1
authorJoonbum Ko <joonbum.ko@samsung.com>
Tue, 5 Jan 2021 04:04:29 +0000 (13:04 +0900)
committerJoonbum Ko <joonbum.ko@samsung.com>
Tue, 9 Mar 2021 08:45:14 +0000 (17:45 +0900)
 - In an exceptional situation, there are cases where
  tpl_gsource_destroy should be called inside gthread.
 - In this case, if a source whose type is SOURCE_TYPE_NORMAL
  tries to destroy through finalizer, deadlock may occur.
   Therefore, when destroying in the same thread,
  destroy_in_thread must be set to FALSE.

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

index 5678755..f178def 100644 (file)
@@ -293,7 +293,7 @@ tpl_gsource_create(tpl_gthread *thread, void *data, int fd,
 }
 
 void
-tpl_gsource_destroy(tpl_gsource *source)
+tpl_gsource_destroy(tpl_gsource *source, tpl_bool_t destroy_in_thread)
 {
        if (g_source_is_destroyed(&source->gsource)) {
                TPL_WARN("gsource(%p) already has been destroyed.",
@@ -301,20 +301,25 @@ tpl_gsource_destroy(tpl_gsource *source)
                return;
        }
 
-       if (source->type == SOURCE_TYPE_NORMAL &&
-               source->finalizer != NULL) {
-               g_mutex_lock(&source->thread->thread_mutex);
+       if (destroy_in_thread) {
+               if (source->type == SOURCE_TYPE_NORMAL) {
+                       g_mutex_lock(&source->thread->thread_mutex);
 
-               tpl_gsource_send_event(source->finalizer, 1);
-
-               g_cond_wait(&source->thread->thread_cond, &source->thread->thread_mutex);
-               g_mutex_unlock(&source->thread->thread_mutex);
-       }
+                       tpl_gsource_send_event(source->finalizer, 1);
 
+                       g_cond_wait(&source->thread->thread_cond, &source->thread->thread_mutex);
+                       g_mutex_unlock(&source->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);
+                       source->finalizer = NULL;
+               }
 
-       if (!g_source_is_destroyed(&source->gsource) &&
-               !(source->type == SOURCE_TYPE_DISPOSABLE ||
-                 source->type == SOURCE_TYPE_FINALIZER)) {
                g_source_remove_unix_fd(&source->gsource, source->tag);
                g_source_destroy(&source->gsource);
                g_source_unref(&source->gsource);
index 4da3828..06d32e6 100644 (file)
@@ -89,9 +89,12 @@ tpl_gsource_create(tpl_gthread *thread, void *data, int fd,
  * Detach the passed tpl_gsource from thread and destroy it.
  *
  * @param source Pointer to tpl_gsource to destroy.
+ * @param destroy_in_thread TRUE if destroy in thread through eventfd, FALSE otherwise.
+ *  It is valid only when SOURCE_TYPE is NORMAL.
+ * @see tpl_gsource_type_t tpl_gsource_create
  */
 void
-tpl_gsource_destroy(tpl_gsource *source);
+tpl_gsource_destroy(tpl_gsource *source, tpl_bool_t destroy_in_thread);
 
 /**
  * Send an event to dispatch the gsource attached to the thread.
index 76947c6..c0e1416 100644 (file)
@@ -227,7 +227,7 @@ __thread_func_tdm_dispatch(tpl_gsource *gsource)
                                tdm_err);
                TPL_WARN("tdm_source(%p) will be removed from thread.", gsource);
 
-               tpl_gsource_destroy(gsource);
+               tpl_gsource_destroy(gsource, TPL_FALSE);
 
                wl_egl_display->tdm_source = NULL;
 
@@ -521,7 +521,7 @@ _thread_fini(void *data)
        tpl_wl_egl_display_t *wl_egl_display = (tpl_wl_egl_display_t *)data;
 
        if (wl_egl_display->tdm_initialized)
-               tpl_gsource_destroy(wl_egl_display->tdm_source);
+               tpl_gsource_destroy(wl_egl_display->tdm_source, TPL_FALSE);
        if (wl_egl_display->wl_initialized)
                _thread_wl_display_fini(wl_egl_display);
 }
@@ -617,7 +617,7 @@ __tpl_wl_egl_display_init(tpl_display_t *display)
 
 free_display:
        if (wl_egl_display->thread) {
-               tpl_gsource_destroy(wl_egl_display->tdm_source);
+               tpl_gsource_destroy(wl_egl_display->tdm_source, TPL_TRUE);
                tpl_gthread_destroy(wl_egl_display->thread, _thread_fini);
        }
 
@@ -644,12 +644,12 @@ __tpl_wl_egl_display_fini(tpl_display_t *display)
                                  wl_egl_display->wl_display);
 
                if (wl_egl_display->gsource) {
-                       tpl_gsource_destroy(wl_egl_display->gsource);
+                       tpl_gsource_destroy(wl_egl_display->gsource, TPL_TRUE);
                        wl_egl_display->gsource = NULL;
                }
 
                if (wl_egl_display->tdm_source && wl_egl_display->tdm_initialized) {
-                       tpl_gsource_destroy(wl_egl_display->tdm_source);
+                       tpl_gsource_destroy(wl_egl_display->tdm_source, TPL_TRUE);
                        wl_egl_display->tdm_source = NULL;
                }