From cb176af61a52c48c85cce74af397eaedcf65848d Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Fri, 2 Dec 2022 16:17:32 +0900 Subject: [PATCH] utils_gthread: Prevent deadlock caused by wait_idle Deadlock situation: Multi-threaded and multi surfaces for each thread T2: call pause_in_idle()->wait_idle() cond_wait() until idle signaled T1: call wait_idle() wait for lock idle_mutex T2: _thread_idle_cb unlock idle_mutex, set is_idle to TPL_TRUE and wait to lock pause_mutex T1: change is_idle to TPL_FALSE cond_wait() T2: cannot exit from while loop still cond_wait() - is_idle changing should be set TPL_FALSE after cond_wait finished Change-Id: I44292e486a1b9f686ec28bc0ae10ddedf94a48e3 Signed-off-by: Joonbum Ko --- src/tpl_utils_gthread.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/tpl_utils_gthread.c b/src/tpl_utils_gthread.c index 208d881..bdc1109 100644 --- a/src/tpl_utils_gthread.c +++ b/src/tpl_utils_gthread.c @@ -475,7 +475,7 @@ _thread_idle_cb(gpointer data) g_mutex_lock(>hread->idle_mutex); gthread->is_idle = TPL_TRUE; - g_cond_signal(>hread->idle_cond); + g_cond_broadcast(>hread->idle_cond); g_mutex_unlock(>hread->idle_mutex); /* If the caller thread of tpl_gthread_wait_idle locked the pause_mutex, @@ -498,7 +498,10 @@ tpl_gthread_wait_idle(tpl_gthread *gthread) TPL_DEBUG("[WAIT IDLE] BEGIN"); g_mutex_lock(>hread->idle_mutex); - gthread->is_idle = TPL_FALSE; + if (gthread->is_idle) { + g_mutex_unlock(>hread->idle_mutex); + return; + } idle_source = g_idle_source_new(); if (idle_source == NULL) { @@ -517,8 +520,7 @@ tpl_gthread_wait_idle(tpl_gthread *gthread) /* 200ms timeout */ end_time = g_get_monotonic_time() + (200 * G_TIME_SPAN_MILLISECOND); - - while (!gthread->is_idle) { + do { ret = g_cond_wait_until(>hread->idle_cond, >hread->idle_mutex, end_time); @@ -526,7 +528,10 @@ tpl_gthread_wait_idle(tpl_gthread *gthread) TPL_ERR("wait_idle timeout!"); break; } - } + } while (!gthread->is_idle); + + gthread->is_idle = TPL_FALSE; + g_mutex_unlock(>hread->idle_mutex); TPL_DEBUG("[WAIT IDLE] END"); -- 2.7.4