Remove event sources not invoked when destroying webrtc handle 72/268872/4 accepted/tizen/unified/20220110.135912 submit/tizen/20220107.064244
authorSangchul Lee <sc11.lee@samsung.com>
Tue, 4 Jan 2022 04:59:54 +0000 (13:59 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Tue, 4 Jan 2022 09:01:55 +0000 (18:01 +0900)
A crash can happen with the previous codes.

It is fixed by removing event sources of idle callbacks
which are not invoked yet before destroying webrtc handle.

[Version] 0.3.39
[Issue Type] Bug fix

Change-Id: Icff390fdd63ee2aa7bfeedd547d63dbb3e0f5d5a

include/webrtc_private.h
packaging/capi-media-webrtc.spec
src/webrtc.c
src/webrtc_private.c

index 40518c37083d31b97cba767e35d226e50b97a055..b6f3e210f1bfd2c76b1558a41235f587e047acf6 100644 (file)
@@ -420,6 +420,16 @@ typedef struct _webrtc_negotiation_states_s {
        webrtc_ice_connection_state_e ice_connection_state;
 } webrtc_negotiation_states_s;
 
+typedef enum _idle_cb_type_e {
+       IDLE_CB_TYPE_STATE,
+       IDLE_CB_TYPE_ERROR,
+       IDLE_CB_TYPE_PEER_CONNECTION_STATE_CHANGE,
+       IDLE_CB_TYPE_SIGNALING_STATE_CHANGE,
+       IDLE_CB_TYPE_ICE_GATHERING_STATE_CHANGE,
+       IDLE_CB_TYPE_ICE_CONNECTION_STATE_CHANGE,
+       IDLE_CB_TYPE_NUM
+} idle_cb_type_e;
+
 typedef struct _webrtc_s {
        webrtc_ini_s ini;
        guint stats_timer_src;
@@ -447,6 +457,8 @@ typedef struct _webrtc_s {
        GHashTable *data_channels;
        GHashTable *track_build_contexts;
 
+       guint idle_cb_event_source_ids[IDLE_CB_TYPE_NUM];
+
        webrtc_callbacks_s error_cb;
        webrtc_callbacks_s state_changed_cb;
        webrtc_callbacks_s peer_connection_state_change_cb;
@@ -622,6 +634,7 @@ int _get_rtp_packet_drop_probability(webrtc_s *webrtc, unsigned int source_id, f
 void _invoke_state_changed_cb(webrtc_s *webrtc, webrtc_state_e old, webrtc_state_e new);
 void _post_state_cb_in_idle(webrtc_s *webrtc, webrtc_state_e new_state);
 void _post_error_cb_in_idle(webrtc_s *webrtc, webrtc_error_e error);
+void _remove_remained_event_sources(webrtc_s *webrtc);
 
 void _connect_and_append_signal(GList **signals, GObject *obj, const char *sig_name, GCallback cb, gpointer user_data);
 void _disconnect_signal(gpointer data);
index bcc19cbf3f061b922ceba6125a38ebb9e612ffa6..98901a362ab516f0b9f9653a3ce7086c7b90e81e 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-webrtc
 Summary:    A WebRTC library in Tizen Native API
-Version:    0.3.38
+Version:    0.3.39
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index fd996f3039c9c539a3b0df77494d6af2454e9e74..436f9ee934df4cd88596c9504a5e831e4316516a 100644 (file)
@@ -128,6 +128,8 @@ int webrtc_destroy(webrtc_h webrtc)
 
        locker = g_mutex_locker_new(&_webrtc->mutex);
 
+       _remove_remained_event_sources(_webrtc);
+
        _webrtc->pend_state = WEBRTC_STATE_IDLE;
 
        _unset_stats_timer(_webrtc);
index 9bb26f9f58840555296af109360c1c2671da9111..e12632c0d50976a4ca111b6b75d1486c7d0d2e04 100644 (file)
@@ -540,18 +540,9 @@ static gboolean __bus_watch_cb(GstBus *bus, GstMessage *message, gpointer user_d
 }
 //LCOV_EXCL_STOP
 
-typedef enum _post_idle_cb_type_e {
-       POST_IDLE_CB_TYPE_STATE,
-       POST_IDLE_CB_TYPE_ERROR,
-       POST_IDLE_CB_TYPE_PEER_CONNECTION_STATE_CHANGE,
-       POST_IDLE_CB_TYPE_SIGNALING_STATE_CHANGE,
-       POST_IDLE_CB_TYPE_ICE_GATHERING_STATE_CHANGE,
-       POST_IDLE_CB_TYPE_ICE_CONNECTION_STATE_CHANGE
-} post_idle_cb_type_e;
-
 typedef struct _idle_userdata {
        webrtc_s *webrtc;
-       post_idle_cb_type_e type;
+       idle_cb_type_e type;
        union {
                webrtc_state_e state;
                webrtc_error_e error;
@@ -582,11 +573,12 @@ static gboolean __idle_cb(gpointer user_data)
        webrtc = data->webrtc;
 
        switch (data->type) {
-       case POST_IDLE_CB_TYPE_STATE: {
+       case IDLE_CB_TYPE_STATE: {
                webrtc_state_e old_state;
 
                g_mutex_lock(&webrtc->mutex);
 
+               webrtc->idle_cb_event_source_ids[data->type] = 0;
                old_state = webrtc->state;
                webrtc->state = data->new.state;
 
@@ -595,19 +587,24 @@ static gboolean __idle_cb(gpointer user_data)
                _invoke_state_changed_cb(webrtc, old_state, webrtc->state);
                break;
        }
-       case POST_IDLE_CB_TYPE_ERROR:
+       case IDLE_CB_TYPE_ERROR:
+               webrtc->idle_cb_event_source_ids[data->type] = 0;
                __invoke_error_cb(webrtc, data->new.error);
                break;
-       case POST_IDLE_CB_TYPE_PEER_CONNECTION_STATE_CHANGE:
+       case IDLE_CB_TYPE_PEER_CONNECTION_STATE_CHANGE:
+               webrtc->idle_cb_event_source_ids[data->type] = 0;
                __invoke_peer_connection_state_change_cb(webrtc, data->new.peer_connection_state);
                break;
-       case POST_IDLE_CB_TYPE_SIGNALING_STATE_CHANGE:
+       case IDLE_CB_TYPE_SIGNALING_STATE_CHANGE:
+               webrtc->idle_cb_event_source_ids[data->type] = 0;
                __invoke_signaling_state_change_cb(webrtc, data->new.signaling_state);
                break;
-       case POST_IDLE_CB_TYPE_ICE_GATHERING_STATE_CHANGE:
+       case IDLE_CB_TYPE_ICE_GATHERING_STATE_CHANGE:
+               webrtc->idle_cb_event_source_ids[data->type] = 0;
                __invoke_ice_gathering_state_change_cb(webrtc, data->new.ice_gathering_state);
                break;
-       case POST_IDLE_CB_TYPE_ICE_CONNECTION_STATE_CHANGE:
+       case IDLE_CB_TYPE_ICE_CONNECTION_STATE_CHANGE:
+               webrtc->idle_cb_event_source_ids[data->type] = 0;
                __invoke_ice_connection_state_change_cb(webrtc, data->new.ice_connection_state);
                break;
        default:
@@ -617,6 +614,20 @@ static gboolean __idle_cb(gpointer user_data)
        return G_SOURCE_REMOVE;
 }
 
+void _remove_remained_event_sources(webrtc_s *webrtc)
+{
+       int i;
+       RET_IF(webrtc == NULL, "webrtc is NULL");
+
+       for (i = IDLE_CB_TYPE_STATE; i < IDLE_CB_TYPE_NUM; i++) {
+               if (webrtc->idle_cb_event_source_ids[i] == 0)
+                       continue;
+               g_source_remove(webrtc->idle_cb_event_source_ids[i]);
+               LOG_DEBUG("idle_cb_event_source_ids[%d] source id[%u]", i, webrtc->idle_cb_event_source_ids[i]);
+               webrtc->idle_cb_event_source_ids[i] = 0;
+       }
+}
+
 void _post_state_cb_in_idle(webrtc_s *webrtc, webrtc_state_e new_state)
 {
        idle_userdata_s *data;
@@ -628,14 +639,15 @@ void _post_state_cb_in_idle(webrtc_s *webrtc, webrtc_state_e new_state)
 
        data = g_new0(idle_userdata_s, 1);
        data->webrtc = webrtc;
-       data->type = POST_IDLE_CB_TYPE_STATE;
+       data->type = IDLE_CB_TYPE_STATE;
        data->new.state = new_state;
 
        webrtc->pend_state = new_state;
 
-       g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, __idle_cb, data, g_free);
+       webrtc->idle_cb_event_source_ids[data->type] = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, __idle_cb, data, g_free);
 
-       LOG_DEBUG("state will be changed [%s] -> [%s]", __state_str[webrtc->state], __state_str[new_state]);
+       LOG_DEBUG("state will be changed [%s] -> [%s], source id[%u]",
+               __state_str[webrtc->state], __state_str[new_state], webrtc->idle_cb_event_source_ids[data->type]);
 }
 
 //LCOV_EXCL_START
@@ -647,12 +659,12 @@ void _post_error_cb_in_idle(webrtc_s *webrtc, webrtc_error_e error)
 
        data = g_new0(idle_userdata_s, 1);
        data->webrtc = webrtc;
-       data->type = POST_IDLE_CB_TYPE_ERROR;
+       data->type = IDLE_CB_TYPE_ERROR;
        data->new.error = error;
 
-       g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, __idle_cb, data, g_free);
+       webrtc->idle_cb_event_source_ids[data->type] = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, __idle_cb, data, g_free);
 
-       LOG_DEBUG("error will occur [0x%x]", error);
+       LOG_DEBUG("error will occur [0x%x], source id[%u]", error, webrtc->idle_cb_event_source_ids[data->type]);
 }
 
 static void __post_peer_connection_state_change_cb_in_idle(webrtc_s *webrtc, webrtc_peer_connection_state_e state)
@@ -663,12 +675,12 @@ static void __post_peer_connection_state_change_cb_in_idle(webrtc_s *webrtc, web
 
        data = g_new0(idle_userdata_s, 1);
        data->webrtc = webrtc;
-       data->type = POST_IDLE_CB_TYPE_PEER_CONNECTION_STATE_CHANGE;
+       data->type = IDLE_CB_TYPE_PEER_CONNECTION_STATE_CHANGE;
        data->new.peer_connection_state = state;
 
-       g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, __idle_cb, data, g_free);
+       webrtc->idle_cb_event_source_ids[data->type] = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, __idle_cb, data, g_free);
 
-       LOG_DEBUG("connection state will be changed to [%u]", state);
+       LOG_DEBUG("connection state will be changed to [%u], source id[%u]", state, webrtc->idle_cb_event_source_ids[data->type]);
 }
 //LCOV_EXCL_STOP
 
@@ -680,12 +692,12 @@ static void __post_signaling_state_change_cb_in_idle(webrtc_s *webrtc, webrtc_si
 
        data = g_new0(idle_userdata_s, 1);
        data->webrtc = webrtc;
-       data->type = POST_IDLE_CB_TYPE_SIGNALING_STATE_CHANGE;
+       data->type = IDLE_CB_TYPE_SIGNALING_STATE_CHANGE;
        data->new.signaling_state = state;
 
-       g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, __idle_cb, data, g_free);
+       webrtc->idle_cb_event_source_ids[data->type] = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, __idle_cb, data, g_free);
 
-       LOG_DEBUG("signaling state will be changed to [%u]", state);
+       LOG_DEBUG("signaling state will be changed to [%u], source id[%u]", state, webrtc->idle_cb_event_source_ids[data->type]);
 }
 
 static void __post_ice_gathering_state_change_cb_in_idle(webrtc_s *webrtc, webrtc_ice_gathering_state_e state)
@@ -696,12 +708,12 @@ static void __post_ice_gathering_state_change_cb_in_idle(webrtc_s *webrtc, webrt
 
        data = g_new0(idle_userdata_s, 1);
        data->webrtc = webrtc;
-       data->type = POST_IDLE_CB_TYPE_ICE_GATHERING_STATE_CHANGE;
+       data->type = IDLE_CB_TYPE_ICE_GATHERING_STATE_CHANGE;
        data->new.ice_gathering_state = state;
 
-       g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, __idle_cb, data, g_free);
+       webrtc->idle_cb_event_source_ids[data->type] = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, __idle_cb, data, g_free);
 
-       LOG_DEBUG("ICE gathering state will be changed to [%u]", state);
+       LOG_DEBUG("ICE gathering state will be changed to [%u], source id[%u]", state, webrtc->idle_cb_event_source_ids[data->type]);
 }
 
 //LCOV_EXCL_START
@@ -713,12 +725,12 @@ static void __post_ice_connection_state_change_cb_in_idle(webrtc_s *webrtc, webr
 
        data = g_new0(idle_userdata_s, 1);
        data->webrtc = webrtc;
-       data->type = POST_IDLE_CB_TYPE_ICE_CONNECTION_STATE_CHANGE;
+       data->type = IDLE_CB_TYPE_ICE_CONNECTION_STATE_CHANGE;
        data->new.ice_connection_state = state;
 
-       g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, __idle_cb, data, g_free);
+       webrtc->idle_cb_event_source_ids[data->type] = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, __idle_cb, data, g_free);
 
-       LOG_DEBUG("ICE connection state will be changed to [%u]", state);
+       LOG_DEBUG("ICE connection state will be changed to [%u], source id[%u]", state, webrtc->idle_cb_event_source_ids[data->type]);
 }
 //LCOV_EXCL_STOP