From f16364564932ac61782bae34b37a1ba1d907275c Mon Sep 17 00:00:00 2001 From: Eunhae Choi Date: Tue, 28 Mar 2017 12:56:03 +0900 Subject: [PATCH] [0.3.54] resolve deadlock and mem leak when remove idle event Change-Id: I370b0a9e9761219ff1daeed3e9fb59dc63fb3c95 --- packaging/capi-media-player.spec | 2 +- src/player.c | 98 +++++++++++++++++++--------------------- 2 files changed, 48 insertions(+), 52 deletions(-) diff --git a/packaging/capi-media-player.spec b/packaging/capi-media-player.spec index a7a35e8..d3214c2 100644 --- a/packaging/capi-media-player.spec +++ b/packaging/capi-media-player.spec @@ -1,6 +1,6 @@ Name: capi-media-player Summary: A Media Player API -Version: 0.3.53 +Version: 0.3.54 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/player.c b/src/player.c index 67d07a8..1937cf5 100644 --- a/src/player.c +++ b/src/player.c @@ -482,8 +482,8 @@ static void set_null_user_cb_lock(callback_cb_info_s * cb_info, muse_player_even if (_player_need_sync_context(event)) _player_remove_idle_event(cb_info, event, false); - else - set_null_user_cb(cb_info, event); + + set_null_user_cb(cb_info, event); if (lock) g_mutex_unlock(&cb_info->event_queue.mutex); @@ -1333,78 +1333,74 @@ static void _player_remove_idle_event(callback_cb_info_s *cb_info, muse_player_e g_return_if_fail(cb_info); player_event_queue *ev = &cb_info->event_queue; _player_cb_data *event_data = NULL; + GList *list = NULL; g_mutex_lock(&ev->idle_ev_mutex); if (ev->idle_ev_list == NULL) { LOGD("No idle event is remained."); - } else { - GList *list = NULL; - list = ev->idle_ev_list; - - LOGD("remove idle event [%d] or all[%d]", event_type, remove_all); - - while (list) { - event_data = list->data; - - if (!event_data) { - list = g_list_next(list); - LOGW("Fail to remove idle event. The data is NULL"); - } else { - if (g_mutex_trylock(&event_data->event_mutex)) { - bool ret = FALSE; + g_mutex_unlock(&ev->idle_ev_mutex); + return; + } - list = g_list_next(list); + LOGD("remove idle event[%d] or all[%d]", event_type, remove_all); - if (remove_all || (event_data->int_data == event_type)) { + for (list = ev->idle_ev_list; list; list = g_list_next(list)) { + event_data = list->data; - LOGD("remove idle event [%p:%d]", event_data, event_data->int_data); + if (!event_data) { + LOGW("Fail to remove idle event. The data is NULL"); + continue; + } - ret = g_idle_remove_by_data(event_data); - if (ret == FALSE) { - /* will be handled at _player_event_job_function() as an exception */ - event_data->cb_info = NULL; - LOGW("failed to remove, idle callback will be called later"); - } else { - /* set cb to null */ - set_null_user_cb(cb_info, event_data->int_data); - } + if (g_mutex_trylock(&event_data->event_mutex)) { - ev->idle_ev_list = g_list_remove(ev->idle_ev_list, (gpointer)event_data); + gboolean ret = FALSE; + if (remove_all || (event_data->int_data == event_type)) { - g_mutex_unlock(&event_data->event_mutex); + LOGD("remove idle event [%p:%d]", event_data, event_data->int_data); - if (ret == TRUE) { - g_mutex_clear(&event_data->event_mutex); + ret = g_idle_remove_by_data(event_data); + if (ret == FALSE) { + /* will be handled at _player_event_job_function() as an exception */ + event_data->cb_info = NULL; + LOGW("failed to remove, idle callback will be called later"); + } - g_free(event_data); - event_data = NULL; + /* set cb to null */ + set_null_user_cb(cb_info, event_data->int_data); + ev->idle_ev_list = g_list_remove(ev->idle_ev_list, (gpointer)event_data); - LOGD("remove idle event done"); - } /* else : will be handled if the cb is called. */ + g_mutex_unlock(&event_data->event_mutex); - if (!remove_all) { - LOGD("remove idle [%d] event", event_type); - g_mutex_unlock(&ev->idle_ev_mutex); - return; - } - } else { - g_mutex_unlock(&event_data->event_mutex); + if (ret == TRUE) { + g_mutex_clear(&event_data->event_mutex); + if (event_data->recv_data) { + g_free(event_data->recv_data->buffer); + g_free(event_data->recv_data); } - } else { - LOGW("event(%d) lock failed. it's being called...", event_data->int_data); - } + g_free(event_data); + event_data = NULL; + LOGD("remove idle event done"); + } /* else : will be handled if the cb is called. */ + } else { + g_mutex_unlock(&event_data->event_mutex); } + } else { + LOGW("event(%d) lock failed. it's being called...", event_data->int_data); } - if (remove_all) { - g_list_free(ev->idle_ev_list); - ev->idle_ev_list = NULL; - } + /* continue: keep checking next event_data */ + } + + if (remove_all) { + g_list_free(ev->idle_ev_list); + ev->idle_ev_list = NULL; } g_mutex_unlock(&ev->idle_ev_mutex); + LOGD("LEAVE"); return; } -- 2.7.4