n00b: signals with an extensible message

Tim Hockin thockin at hockin.org
Wed Feb 17 19:48:17 PST 2010


OK, I think I have this, except the client side is leaking (I'm not
100% sure the server isn't leaking, but valgrind gives it the OK).
Vlagrind flags teh client pretty obviously.


==23080== LEAK SUMMARY:
==23080==    definitely lost: 0 bytes in 0 blocks
==23080==    indirectly lost: 0 bytes in 0 blocks
==23080==      possibly lost: 3,348,580 bytes in 26,903 blocks
==23080==    still reachable: 6,766,515 bytes in 45,857 blocks
==23080==         suppressed: 0 bytes in 0 blocks


Server is passing an a{sv} signal.  The client is receiving it, and
the callback gets invoked.  I don't know where the leak is, but the
more of these events I send the bigger the numbers get in valgrind.

Here is the client code:

#include <glib.h>
#include <glib/ghash.h>
#include <dbus/dbus-glib.h>
#include <stdlib.h>

static void handler(DBusGProxy* proxy, GHashTable *hash, gpointer userData)
{
  GHashTableIter it;
  gpointer key;
  gpointer value;
  g_hash_table_iter_init(&it, hash);
  while (g_hash_table_iter_next(&it, &key, &value)) {
    g_print("%s\n", (const char *)key);
  }
}

int main(int argc, const char *argv[])
{
  DBusGConnection *bus;
  DBusGProxy *remoteValue;
  GMainLoop* mainloop;
  GError *error = NULL;

  g_type_init();

  mainloop = g_main_loop_new(NULL, FALSE);

  bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);

  remoteValue =
  dbus_g_proxy_new_for_name(bus,
                            "org.hockin.TestService",
                            "/org/hockin/TestObject",
                            "org.hockin.TestInterface");

  dbus_g_proxy_add_signal(remoteValue, "event",
                          dbus_g_type_get_map("GHashTable",
                                              G_TYPE_STRING, G_TYPE_VALUE),
                          G_TYPE_INVALID);

  dbus_g_proxy_connect_signal(remoteValue, "event",
                              G_CALLBACK(handler), NULL, NULL);

  g_main_loop_run(mainloop);

  return 0;
}


Can anyone clue me in?





On Tue, Feb 16, 2010 at 7:38 PM, Tim Hockin <thockin at hockin.org> wrote:
> On Tue, Feb 16, 2010 at 7:35 AM, Simon McVittie
> <simon.mcvittie at collabora.co.uk> wrote:
>> On Tue, 16 Feb 2010 at 07:38:44 -0600, Schmottlach, Glenn wrote:
>>> Another alternative is to encode your payload using XML or (preferably)
>>> JSON on top of D-Bus.
>>
>> I'd discourage this unless there's already a common format for the payload, and
>> perhaps even then (for instance, it'd make sense to transfer rich text as HTML
>> rather than inventing a D-Bus serialization, but Telepathy has a D-Bus
>> serialization for vCards).
>>
>> If you use JSON or XML, your recipient needs two libraries and two type
>> systems; in practice that means they'll be dealing with three subtly different
>> type systems (JSON, D-Bus, and whatever their language/runtime uses).
>>
>> In particular, D-Bus has all the building blocks that JSON does, with the
>> notable exception of the special constant 'null' in JSON (which can be worked
>> around, if necessary). JSON objects/dictionaries are D-Bus 'a{sv}', JSON lists
>> are D-Bus 'av' (or some more specific type), JSON strings (Unicode) are D-Bus
>> 's' (UTF-8), and so on.
>>
>> To represent a simple C struct that will break ABI in the future, something
>> like:
>>
>>    struct Meme {
>>        int32_t badger;
>>        char *mushroom;
>>        size_t n_snakes;
>>        uint64_t *snakes;    /* an array of length n_snakes */
>>        bool magical_trevor;
>>    } my_meme = {
>>        42,
>>        "fungus",
>>        2,
>>        { 23, 37 },
>>        TRUE,
>>    };
>>
>> I'd use an a{sv} something like this (using dbus-python notation to make the
>> types explicit - this can be written more concisely of course):
>>
>>    dbus.Dictionary({
>>        dbus.String('badger'):         dbus.Int32(42),
>>        dbus.String('mushroom'):       dbus.String('fungus'),
>>        dbus.String('snakes'):         dbus.Array([23, 37], signature='x'),
>>        dbus.String('magical-trevor'): dbus.Boolean(True),
>>    }, signature='sv')
>>
>> In other words, represent your struct as a dictionary, using the D-Bus type
>> system. The receiver can detect missing or extra members and do whatever it
>> wants with them (best practice is usually to ignore extra members and define a
>> sane default for missing members, but if that's not always acceptable, you
>> could define a local convention like "if there are unrecognised fields starting
>> with '!' the message must be rejected").
>>
>> Telepathy <http://telepathy.freedesktop.org/spec/> contains many examples of
>> a{sv} being used as an extensible payload format.
>
> Thanks for the pointer.  I found the tp_asv helper routines, but I am
> having trouble finding the marshalling code. Any deeper pointers you
> can share?
>
> Tim
>


More information about the dbus mailing list