Set timer asynchronously to avoid deadlock 28/260928/2
authorSuyeon Hwang <stom.hwang@samsung.com>
Wed, 7 Jul 2021 05:37:34 +0000 (14:37 +0900)
committerSuyeon Hwang <stom.hwang@samsung.com>
Wed, 7 Jul 2021 07:28:06 +0000 (16:28 +0900)
If 'tts_stop()' or 'tts_pause()' is called when play thread calls '__unset_policy_for_playing()',
deadlock can occur because 'tts_stop()' or 'tts_pause()' blocks main thread until play thread is
finished, although play thread also blocks the thread by 'ecore_main_loop_thread_safe_call_sync()'
until ecore main is available.

This patch prevents deadlock using function 'ecore_main_loop_thread_safe_call_async()'.
By this function, play thread does not have to block the thread any more stil wait main thread.

Change-Id: I06af24bdc365d8ab1032f42256d7fe770625003e
Signed-off-by: Suyeon Hwang <stom.hwang@samsung.com>
server/ttsd_player.c

index acd60eb..ebbb5ef 100644 (file)
@@ -94,6 +94,10 @@ static bool g_is_set_policy;
 
 // static bool ducking_flag;
 
+/* CAUTION!
+If you change this constant value. Please check the function '__set_timer_for_delay_recover()'.
+If you choose too big value, it may cause integer overflow issue.
+*/
 #define SND_MGR_DUCKING_DURATION 500
 
 static struct timespec g_policy_set_time;
@@ -462,7 +466,7 @@ static void __set_policy_for_playing(int volume)
        return;
 }
 
-static Eina_Bool __delay_unset_policy(void* data)
+static Eina_Bool __delay_recover_background_volume(void* data)
 {
        pthread_mutex_lock(&g_delayed_unset_policy_mutex);
        __recover_background_volume();
@@ -473,11 +477,12 @@ static Eina_Bool __delay_unset_policy(void* data)
        return EINA_FALSE;
 }
 
-static void* __set_timer_for_unset(void* data)
+static void __set_timer_for_delay_recover(void* data)
 {
-       g_delayed_unset_policy_timer = ecore_timer_add(0.5, __delay_unset_policy, NULL);
-       SLOG(LOG_INFO, tts_tag(), "[BG] Delayed unset policy (%p)", g_delayed_unset_policy_timer);
-       return 0;
+       long long int diff = (intptr_t)data;
+       double delay = (double)(SND_MGR_DUCKING_DURATION - diff) / 1000.0;
+       g_delayed_unset_policy_timer = ecore_timer_add(delay, __delay_recover_background_volume, NULL);
+       SLOG(LOG_INFO, tts_tag(), "[BG] Delayed unset policy (%p), delay(%f)", g_delayed_unset_policy_timer, delay);
 }
 
 static void __unset_policy_for_playing()
@@ -517,12 +522,12 @@ static void __unset_policy_for_playing()
                        SLOG(LOG_INFO, tts_tag(), "[BG] Direct unset policy");
                        __recover_background_volume();
                } else {
-                       ecore_main_loop_thread_safe_call_sync(__set_timer_for_unset, NULL);
+                       intptr_t ptr_diff = diff;
+                       ecore_main_loop_thread_safe_call_async(__set_timer_for_delay_recover, (void*)ptr_diff);
                }
        }
        pthread_mutex_unlock(&g_delayed_unset_policy_mutex);
 
-       __recover_background_volume();
        g_is_set_policy = false;
        SLOG(LOG_ERROR, tts_tag(), "[BG] g_is_set_policy(%d)", g_is_set_policy);