thread-safety of counters
Simon McVittie
simon.mcvittie at collabora.co.uk
Mon Feb 23 04:56:30 PST 2015
On 23/02/15 11:23, Adrian Szyndela wrote:
> Let's consider a simple test program that:
> 1. creates a D-Bus connection;
> 2. creates a few threads that share the connection;
> 3. then, threads perform method calls over the connection.
This is meant to work, but I don't recommend it. I would recommend GIO's
GDBus module, particularly for multi-threaded D-Bus: its design is
explicitly multi-threaded.
Please be careful to distinguish between D-Bus, the protocol, and
libdbus, the reference implementation of that protocol (as shipped
alongside dbus-daemon in dbus.git). I consider GDBus to be a better
D-Bus implementation for most purposes than libdbus.
> If answer is no, then I have another question: is there any place that
> describes what is thread-safe in dbus and what is not?
libdbus is theoretically thread-safe, but its level of thread-safety is
mostly developer folklore rather than something that is explicitly
documented. I believe sharing a "large" object like a DBusConnection
(perhaps also a DBusServer?) between multiple threads is *meant* to
work, whereas any API call other than ref/unref on a DBusMessage
requires the calling thread to "own" that message, and I'm not sure
about objects of intermediate size like DBusPendingCall.
One DBusConnection per thread is more likely to work than one
DBusConnection shared between many threads; if you do share one
DBusConnection between many threads, then restricting yourself to
"dispatching" in at most one "owner" thread, and only performing
blocking method calls in the other threads (as QtDBus does), is more
likely to work than anything more complicated.
Unfortunately, libdbus was designed to be suitable for all uses with few
assumptions (e.g. any or no main-loop abstraction, any or no
multi-threading design), with the predictable result that instead of
doing one thing well and everything else not at all, it does lots of
things but none of them very well. D-Bus reimplementations like GDBus,
and libdbus wrappers like QtDBus, can do a lot better by fixing some of
the details: for instance, GDBus requires the GLib main loop (which it
runs in a worker thread so that calling code is not necessarily required
to use it too, although that is also encouraged), and QtDBus requires
the Qt main loop.
> There are two messages involved, but both point to the same counter
> (connection->transport->live_messages).
I thought this counter was meant to be protected by one of the
connection's mutexes (it has three - dispatch_mutex, io_path_mutex and
mutex - because libdbus tries to be all things to all people and support
an assortment of unlikely threading models). But I could be wrong...
> As a conclusion, I suggest changing DBusCounter's refcount from int to
> DBusAtomic, as in DBusMessage.
This seems reasonable, but it would be good to know whether the counter
is meant to be protected by a mutex. If so, why was that mutex not
sufficient here? and if not, how do we avoid getting an incorrect value
in the counter via concurrent access from different threads?
--
Simon McVittie
Collabora Ltd. <http://www.collabora.com/>
More information about the dbus
mailing list