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