Re: [PATCH BlueZ] gdbus: Fix removal of filter after last filter_data

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Jun 25, 2012 at 5:51 AM, Luiz Augusto von Dentz
<luiz.dentz@xxxxxxxxx> wrote:
> Hi Lucas,
>
> On Sat, Jun 23, 2012 at 5:02 PM, Lucas De Marchi
> <lucas.demarchi@xxxxxxxxxxxxxx> wrote:
>> If there's a signal watch that's also watching for name
>> (data->name_watch) currently we are trying to remove the message_filter
>> twice since we may have the following call chain:
>>
>> filter_data_remove_callback()
>>  filter_data_free()
>>    g_dbus_remove_watch()
>>      filter_data_remove_callback()
>>        filter_data_free()
>>        dbus_connection_remove_filter()
>>  dbus_connection_remove_filter()
>>
>> Because of this we can't currently watch for signals passing the bus
>> name. After this patch we don't have this issue anymore.
>>
>> We fix this by checking if we are the last filter_data before calling
>> filter_data_free and thus not calling dbus_connection_remove_filter()
>> twice.
>> ---
>>  gdbus/watch.c | 12 +++++++++---
>>  1 file changed, 9 insertions(+), 3 deletions(-)
>>
>> diff --git a/gdbus/watch.c b/gdbus/watch.c
>> index 9a716b0..6fed264 100644
>> --- a/gdbus/watch.c
>> +++ b/gdbus/watch.c
>> @@ -350,6 +350,7 @@ static gboolean filter_data_remove_callback(struct filter_data *data,
>>                                                struct filter_callback *cb)
>>  {
>>        DBusConnection *connection;
>> +       struct filter_data *data_next;
>>
>>        data->callbacks = g_slist_remove(data->callbacks, cb);
>>        data->processed = g_slist_remove(data->processed, cb);
>> @@ -376,12 +377,17 @@ static gboolean filter_data_remove_callback(struct filter_data *data,
>>
>>        connection = dbus_connection_ref(data->connection);
>>        listeners = g_slist_remove(listeners, data);
>> +
>> +       /*
>> +        * filter_data_free() may remove the latest data - we need to check
>> +        * before it runs if it's our duty to remove the filter
>> +        */
>> +       data_next = filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
>> +                                                                       NULL);
>>        filter_data_free(data);
>>
>>        /* Remove filter if there are no listeners left for the connection */
>> -       data = filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
>> -                                       NULL);
>> -       if (data == NULL)
>> +       if (data_next == NULL)
>>                dbus_connection_remove_filter(connection, message_filter,
>>                                                NULL);
>>
>> --
>> 1.7.11
>
> Hmm do you have checks enabled in libdbus? It seems this is cause by:
>
> #ifndef DBUS_DISABLE_CHECKS
>  if (filter == NULL)
>    {
>      _dbus_warn_check_failed ("Attempt to remove filter function %p
> user data %p, but no such filter has been added\n",
>                               function, user_data);
>      return;
>    }
> #endif

Probably... this is the stock libdbus from Archlinux. I also found
interest that all possible users of g_dbus_add_signal_watch() with a
bus name were passing a NULL, which is clearly wrong. That made me
think it was like this to workaround this bug.


>
> Anyway I couldn't reproduce by changing ofono with stock libdbus from
> FC 17, although I see the problem just by looking at the code, but
> there other places where this need to be checked as well and the code
> could be simplified:
>
> diff --git a/gdbus/watch.c b/gdbus/watch.c
> index 9a716b0..d749176 100644
> --- a/gdbus/watch.c
> +++ b/gdbus/watch.c
> @@ -376,15 +376,14 @@ static gboolean
> filter_data_remove_callback(struct filter_data *data,
>
>        connection = dbus_connection_ref(data->connection);
>        listeners = g_slist_remove(listeners, data);
> -       filter_data_free(data);
>
>        /* Remove filter if there are no listeners left for the connection */
> -       data = filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
> -                                       NULL);
> -       if (data == NULL)
> +       if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
> +                                                               NULL) == NULL)
>                dbus_connection_remove_filter(connection, message_filter,
>                                                NULL);
>
> +       filter_data_free(data);
>        dbus_connection_unref(connection);
>
>        return TRUE;

ahn... right. We already removed data from listeners list so we can
call dbus_connection_remove_filter() before filter_data_free().


Ack.
Lucas De Marchi
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux