add user_data_free_func for 'g_dbus_connection_signal_subscribe' 56/236556/2
authorjiyong.min <jiyong.min@samsung.com>
Thu, 18 Jun 2020 05:36:44 +0000 (14:36 +0900)
committerjiyong.min <jiyong.min@samsung.com>
Thu, 18 Jun 2020 07:54:22 +0000 (16:54 +0900)
  - user_data 'listener' is potentially used in a different thread after user_data has been released
    in another thread.
    so, user_data should be passed to user_data_free_func of 'g_dbus_connection_signal_subscribe'.

Change-Id: I0f7dfc9f338857b6dc0691fc0cd08d0ffa0917fe

src/media_controller_ipc.c

index 5d15c4f7c81c928d02960b656bf74f466b002a7c..d42dff35d12f2ba9e6deec3d100b0d3531ebc74f 100644 (file)
@@ -60,7 +60,7 @@ static void __dbus_signal_cb(GDBusConnection *connection,
        gchar *message = NULL;
        gchar *request_id = NULL;
 
-       mc_debug("__dbus_signal_cb Received :");
+       mc_debug_fenter();
 
        g_variant_get(parameters, "(&s&s)", &request_id, &message);
        mc_retm_if_failed(message);
@@ -69,9 +69,10 @@ static void __dbus_signal_cb(GDBusConnection *connection,
        if (!g_strcmp0(request_id, DEFAULT_REQ_ID))
                request_id = NULL;
 
-       mc_secure_debug("Recv: [%s] (id: %s) from %s.%s", message, request_id, interface_name, signal_name);
-
+       mc_secure_debug("Received: [%s] (id: %s) from %s.%s", message, request_id, interface_name, signal_name);
        listener->callback(interface_name, signal_name, message, request_id, listener->user_data);
+
+       mc_debug_fleave();
 }
 
 static void __free_dbus_listener(gpointer data)
@@ -79,12 +80,26 @@ static void __free_dbus_listener(gpointer data)
        mc_ipc_listener_s *listener = (mc_ipc_listener_s *)data;
        if (!listener)
                return;
-       mc_debug("listener[%s] will be unregistered.", listener->key);
-       g_dbus_connection_signal_unsubscribe(listener->dbus_conn, listener->handler);
+
+       mc_debug("listener[%s] will be released.", listener->key);
        g_free(listener->key);
        g_free(listener);
 }
 
+static void __unsubscribe_dbus_signal(gpointer data)
+{
+       mc_ipc_listener_s *listener = (mc_ipc_listener_s *)data;
+       if (!listener)
+               return;
+
+       /* g_dbus_connection_signal_unsubscribe can be called in another thread by apps.
+          so, user_data(listener) should be passed to user_data_free_func(__free_dbus_listener)
+          from g_dbus_connection_signal_subscribe().
+        */
+       mc_debug("listener[%s] will be unsubscribe.", listener->key);
+       g_dbus_connection_signal_unsubscribe(listener->dbus_conn, listener->handler);
+}
+
 static gboolean __is_duplicated_dbus_listener(GList *listener_list, const char *key)
 {
        GList *found_item = NULL;
@@ -207,7 +222,7 @@ int _mc_ipc_register_listener(GList **listener_list, GDBusConnection *connection
                                G_DBUS_SIGNAL_FLAGS_NONE,
                                (GDBusSignalCallback)__dbus_signal_cb,
                                (gpointer)listener,
-                               NULL);
+                               __free_dbus_listener);
 
        if (listener->handler == 0) {
                mc_error("Error signal subscribe");
@@ -238,8 +253,7 @@ int _mc_ipc_unregister_listener(GList **listener_list, const char *interface_nam
        found_item = g_list_find_custom(*listener_list, (gconstpointer)key, __find_dbus_listener_by_key);
        if (found_item) {
                (*listener_list) = g_list_remove_link(*listener_list, found_item);
-               __free_dbus_listener(found_item->data);
-               g_list_free(found_item);
+               g_list_free_full(found_item, __unsubscribe_dbus_signal);
        }
 
        mc_debug("listener[%s.%s] is unregistered. listener_cnt[%d]", interface_name, signal_name, g_list_length(*listener_list));
@@ -253,7 +267,7 @@ int _mc_ipc_unregister_all_listener(GList **listener_list)
 {
        mc_retvm_if(listener_list == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "listener_list is NULL");
 
-       g_list_free_full(*listener_list, __free_dbus_listener);
+       g_list_free_full(*listener_list, __unsubscribe_dbus_signal);
        *listener_list = NULL;
 
        return MEDIA_CONTROLLER_ERROR_NONE;