Two interfaces in the same process

Simon McVittie simon.mcvittie at collabora.co.uk
Thu Oct 25 15:41:12 PDT 2012


On 25/10/12 21:24, bogdanul2003 wrote:
> I use glib bindings for dbus

dbus-glib or GDBus? If you have a choice, I strongly suggest using GDBus.

The short version of this reply is "don't block the main loop". If you
have no choice, read on.

> Will interface Y be blocked if a method call is handled on
> interface X ?

Think about how control gets to your method implementation (if
necessary, make it crash, e.g. with abort(), and look at the resulting
stack trace): a callback from the GLib main loop calls it. So, no, you
can't receive method calls while the main loop that receives them is
blocked in some other callback.

If the implementation of the method on interface X is synchronous (in
dbus-glib: "the sort that has a GError ** parameter", yes, interface Y
will be blocked.

If the implementation of the method on interface X is asynchronous (in
dbus-glib: "the sort that has a DBusGMethodInvocation * parameter") and
it returns to the main loop while deciding how to reply, no, interface Y
will not be blocked.

With GDBus, there is a third option, which is to use multiple threads.
This is not an option in dbus-glib, because dbus-glib is not
thread-safe. In GDBus it's possible, although not necessarily a good
idea. If you don't know whether your code is thread-safe, the answer is
that it isn't; if you believe it to be thread-safe, in practice it
probably still isn't.

> I can't use async calls for the method call on interface X
> (major changes would be required to do so).

To be able to respond to calls to Y.SomeMethod while still "thinking
about" a response to X.SomeOtherMethod, you don't need to use
asynchronous calls in the client process, but you do need to use an
asynchronous (or threaded) implementation of X.SomeOtherMethod in the
service.

(You should call methods asynchronously anyway - see
<http://smcv.pseudorandom.co.uk/2008/11/nonblocking/> - but that isn't
required to solve this particular problem.)

> DBus has one message queue per process?

In dbus-glib, method calls are dispatched from a GMainContext (usually
the default main context). Each DBusGConnection is associated with
exactly one GMainContext, and method implementations can be called if
and only if that GMainContext is currently being iterated by some thread
(e.g. in g_main_context_iteration() or a GMainLoop).

In GDBus, the GDBusConnection receives messages in a separate "worker
thread" and passes them to whatever GMainContext you asked for your
callback to be called in, where they will be dispatched to a callback if
and only if that GMainContext is currently being iterated by some
thread. See its documentation for details of how it chooses a
GMainContext (it's based on the "thread-default main context" concept in
GIO).

> If you will create more then one gloop per process will you have more then
> one message queue?

The simplest rule to follow is "there is only the default GMainContext,
it is iterated in the main thread, and none of my code executes in any
other thread". If you are unable to follow that rule for whatever
reason, make sure you know exactly what's going on, which thread and
main context each function will execute in, and which locks need to be
held while accessing your data structures.

If you're using dbus-glib, you must only call dbus-glib API from one
thread, and iterating a GMainContext with which you associated a
DBusGConnection counts as calling dbus-glib API. In practice that one
thread is nearly always the main thread[1], and that GMainContext is
nearly always the NULL main context.

If you're using GDBus, see its documentation for details of how it
interacts with the thread-default GMainContext.

    S

[1] by which I mean: the thread where main() was called


More information about the dbus mailing list