[0.3.54] resolve deadlock and mem leak when remove idle event 45/121845/1 accepted/tizen_common accepted/tizen_ivi accepted/tizen_mobile accepted/tizen_tv accepted/tizen_wearable accepted/tizen/common/20170404.142301 accepted/tizen/ivi/20170403.130018 accepted/tizen/mobile/20170403.125554 accepted/tizen/tv/20170403.125821 accepted/tizen/unified/20170403.130117 accepted/tizen/wearable/20170403.125913 submit/tizen/20170403.050513
authorEunhae Choi <eunhae1.choi@samsung.com>
Tue, 28 Mar 2017 03:56:03 +0000 (12:56 +0900)
committerEunhae Choi <eunhae1.choi@samsung.com>
Wed, 29 Mar 2017 07:26:30 +0000 (16:26 +0900)
Change-Id: I370b0a9e9761219ff1daeed3e9fb59dc63fb3c95

packaging/capi-media-player.spec
src/player.c

index a7a35e8..d3214c2 100644 (file)
@@ -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
index 67d07a8..1937cf5 100644 (file)
@@ -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;
 }