Skype and DBus: should my client library act as a server?

Thomas Downing tdowning at bomgar.com
Mon Mar 23 05:43:29 PDT 2015


On Sunday, March 22, 2015 08:07:17 Lars Hanisch wrote:
> Am 18.03.2015 um 22:05 schrieb Julien JPK:
> > On 18/03/15 20:33, Simon McVittie wrote:
> >> On 18/03/15 20:00, Julien JPK wrote:
> >>>  - Start sending my requests from another thread.
> >> 
> >> Threads! You had a problem, you solved it with threads, and now you have
> >> two problems working in parallel :-)
> >> 
[snip]
> 
>  I wrote a plugin for the vdr (http://tvdr.de/) to add a DBus interface to
> it (https://github.com/flensrocker/vdr-plugin-dbus2vdr). I also started
> with libdbus, because I thought, like every other lib<core-component>,
> that should be the lib to use. It kind of worked, but had a lot of flaws
> in that multi-threaded environment, my plugin runs.
> 
>  Finally I switched to GDBus and never regret it.
> 
>  My advice: if you want to dig into DBus itself, write a new
> implementation, that fits your needs. But if you just want to use DBus,
> use an implementation the "DBus gurus" point you to. GDBus is way more
> easier to use than libdbus.
> 
> Lars.

For anybody who _really_ wants to, or must, use libdbus in a multi-threaded 
environment:

For reasons not relevant here, I used libdbus, though I am now free to explore 
replacing it with GDBus.  So I wrote a partial libdbus wrapper for our 
multitreaded app to use.  Partial, because I did not create a generic message 
content wrapper, such as proxy code generators etc.

I did integrate libdbus into an extant main epoll loop using the DBusTimeout 
and DBusWatch functions.

What I found was the key: dbus_connection_dispatch.  While this method is on 
the call stack of _any_ thread, certain other libdbus methods are not safe.

The approach I took was to call dbus_connection_send and 
dbus_connection_dispatch from the same dedicated thread.  This thread wakes up 
to do work on any Watch, Timeout, Wakeup callback, when a timeout or watch 
needs service, or when there is a queued message to send.

Arbitrary threads in our app, when sending a message is really just queueing 
that message for later send by the dedicated thread.  Messages received as the 
result of dbus_connection_dispatch are queued for later delivery by a thread 
other than the dedicated thread.

Once this is done, the only other functions that I needed to protect were the 
dbus_message_new* calls.  I wrapped these such that a mutex (or other 
protection) ensure that they block while the dedicated thread is in 
dbus_connection_dispatch.  Note that this implies the correct use of 
dbus_message_ref/unref

Parsing a message, or building a message can be done by an arbitrary thread 
without protection.

To date, all testing using the valgrind suite, -fsanitize and other tools have 
revealed no problems.  The end result is that from the perspective of an 
arbitrary thread using the wrapper, non-blocking messaging, including in-
context delivery of asynchrounous signals, method calls, and method returns 
are all available.

Your mileage may vary, as I don't use all the functions provided by libdbus; 
meaning that there may be other functions unsafe while a thread is in 
dbus_connection_dispatch.

Thomas Downing


More information about the dbus mailing list