Using d-bus from multiple threads?
Havoc Pennington
hp at pobox.com
Mon Aug 23 17:26:36 PDT 2010
Hi,
The intent of the libdbus library (maybe) was that you could have one
thread with the main loop or dbus_connection_read_write_dispatch()
processing incoming messages, while you could have other threads
making method calls and blocking waiting for replies to those method
calls.
However, the implementation of that isn't quite right (judging by bug
reports), and despite near-weekly posts from people trying to use
threads, so far none of those people has really dug in and fixed the
library itself.
dbus-glib is another can of worms; it just has problems everywhere,
getting threads involved just makes it worse. dbus-glib basically was
never finished and has some Bad Ideas in the design. There is a newer
gdbus included in the development version of glib, that is much
better.
What I would say is that if you want to use threads, you're best off
being willing to dive into libdbus and figure out how to address the
issues. Otherwise, what I'd suggest is picking a main loop (libev is a
nice small one, glib GMainContext is a very popular one) and use that
from a single thread. Have your other threads ask the main loop thread
to use libdbus on their behalf. With GMainContext you just have to
queue a G_PRIORITY_DEFAULT "idle" handler (at default priority it
won't wait for idle) which will get your callback running in the main
loop thread. With libev you can do basically the same thing but libev
doesn't do any locking, you have to do it yourself.
If you're wondering what issues are known for libdbus, I believe they
are in bugzilla, at least to the extent that anyone has tracked them
down.
There really isn't much advantage to using threads with libdbus since
you need a main loop (or at least
dbus_connection_read_write_dispatch()) anyhow in order to handle
incoming signals. As discussed in a recent thread though,
read_write_dispatch() lacks a way for other threads to wake it up, so
it won't really work with threads. (This is fairly easy to fix in
libdbus, but it isn't fixed already.) libev has an "async" main loop
event that can be used to wake up the loop from another thread, while
GMainContext has g_main_context_wakeup(), so the main loops solve this
problem.
If you don't know what I'm talking about on any of this, the simplest
is to use dbus-glib *only* for main loop integration
(dbus_connection_setup_for_g_main or whatever it's called) and then
avoid the rest of dbus-glib. Or use a decent binding such as gdbus,
python bindings, javascript bindings, Qt bindings, etc., there are
lots of them.
The problem (best I can tell) is that people trying to use threads are
almost always people doing something "embedded" and they essentially
never contribute upstream, while people not using threads are all the
Linux desktop people, who contribute upstream but don't use threads.
So the people who try to use threads, while numerous, aren't fixing
the library.
Havoc
More information about the dbus
mailing list