gdbus/watch: Fix aborting when removing D-Bus filter
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Tue, 3 Sep 2013 15:00:35 +0000 (18:00 +0300)
committerMarcel Holtmann <marcel@holtmann.org>
Thu, 12 Sep 2013 15:25:23 +0000 (08:25 -0700)
In case of filter_data having a watch to a service name it may call
dbus_connection_remove_filter twice causing libdbus to abort:

process 24723: Attempt to remove filter function 0x4063e0 user data (nil), but no such filter has been added

To fix this the code will now only attempt to call
dbus_connection_remove_filter once in filter_data_free which is the
counterpart of filter_data_get where dbus_connection_add_filter is called.

gdbus/watch.c

index ed3bc42..27720e0 100644 (file)
@@ -281,6 +281,11 @@ static void filter_data_free(struct filter_data *data)
 {
        GSList *l;
 
+       /* Remove filter if there are no listeners left for the connection */
+       if (filter_data_find(data->connection) == NULL)
+               dbus_connection_remove_filter(data->connection, message_filter,
+                                                                       NULL);
+
        for (l = data->callbacks; l != NULL; l = l->next)
                g_free(l->data);
 
@@ -360,8 +365,6 @@ static void service_data_free(struct service_data *data)
 static gboolean filter_data_remove_callback(struct filter_data *data,
                                                struct filter_callback *cb)
 {
-       DBusConnection *connection;
-
        data->callbacks = g_slist_remove(data->callbacks, cb);
        data->processed = g_slist_remove(data->processed, cb);
 
@@ -385,16 +388,8 @@ static gboolean filter_data_remove_callback(struct filter_data *data,
        if (data->registered && !remove_match(data))
                return FALSE;
 
-       connection = dbus_connection_ref(data->connection);
        listeners = g_slist_remove(listeners, data);
-
-       /* Remove filter if there are no listeners left for the connection */
-       if (filter_data_find(connection) == NULL)
-               dbus_connection_remove_filter(connection, message_filter,
-                                               NULL);
-
        filter_data_free(data);
-       dbus_connection_unref(connection);
 
        return TRUE;
 }
@@ -563,6 +558,9 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
                                                                current);
        }
 
+       if (delete_listener == NULL)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
        for (current = delete_listener; current != NULL;
                                        current = delete_listener->next) {
                GSList *l = current->data;
@@ -581,11 +579,6 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
 
        g_slist_free(delete_listener);
 
-       /* Remove filter if there are no listeners left for the connection */
-       if (filter_data_find(connection) == NULL)
-               dbus_connection_remove_filter(connection, message_filter,
-                                               NULL);
-
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
@@ -814,6 +807,4 @@ void g_dbus_remove_all_watches(DBusConnection *connection)
                listeners = g_slist_remove(listeners, data);
                filter_data_call_and_free(data);
        }
-
-       dbus_connection_remove_filter(connection, message_filter, NULL);
 }