Synchronous method in asynchronous signal callback

Simon McVittie simon.mcvittie at collabora.co.uk
Thu May 14 08:54:57 PDT 2015


On 14/05/15 16:16, Marco Bascetta wrote:
> I'm using libdbus with a poll mainloop. I monitor the DBusWatch file
> descriptor to call "dbus_watch_handle" and "dbus_connection_dispatch".

My first recommendation would be to use a main loop designed by people
who have thought a lot about main loops, like GLib, Qt, libevent or
libev, rather than writing your own. I prefer to use GLib myself.

If using GLib, you could use GDBus instead of libdbus: it's an
interoperable D-Bus reimplementation with a much higher-level design
(you probably saw the warnings in the libdbus documentation about how
it's low-level and painful to use). Crucially, it knows which main loop
you can be expected to use (the GLib one) so it can integrate with that
one perfectly; it doesn't have to jump through hoops to be
main-loop-agnostic like libdbus does, which just results in libdbus
integrating with every main loop equally poorly.

Similarly, if using Qt, you could use QtDBus, which is a convenient
wrapper around libdbus.

> It works without deadlock or message missing, but the signals received
> during the "invoke_method" are delayed until another signal is received
> (watch fd unlocks the poll) (and this could occurs much later...)
> 
> Could you suggest me how to resolve this issue without using the
> asynchronous calls only?

My next recommendation would be: relax your constraints, and use
asynchronous calls. Doing a synchronous "pseudo-blocking" call[1] inside
a filter function is never going to work amazingly well.

However, if you cannot do that, I think you might need either a
pipe-to-self[2] or (on modern Linux) an eventfd (which is just a
"cheaper" way to do a pipe-to-self), to wake up the poll() "from a
distance". For instance, in GLib this is g_main_context_wakeup(), which
uses an eventfd on Linux or a pipe elsewhere.

The fact that you need to set force_dispatch makes me suspicious. You
haven't provided pseudocode for your actual main loop or how you hook up
the watch(es), but I wonder whether you aren't using all the necessary
integration points.

dbus-glib is deprecated and should not be used, but
http://cgit.freedesktop.org/dbus/dbus-glib/tree/dbus/dbus-gmain.c does
provide an example of a complete main loop hookup including all the
necessary glue:

* watches
* timeouts
* separate read and write watches for the same fd (yes this is silly,
  but the mainloop integration glue API doesn't give us a way to signal
  that the wants-read/wants-write state has changed, and I don't think
  we can assume that every existing implementation re-polls the flags
  when a watch is disabled and re-enabled)
* dbus_connection_set_wakeup_main_function(), which I think might be
  the one you're missing?

[1] http://smcv.pseudorandom.co.uk/2008/11/nonblocking/
[2] e.g. http://skarnet.org/software/skalibs/libstddjb/selfpipe.html

-- 
Simon McVittie
Collabora Ltd. <http://www.collabora.com/>



More information about the dbus mailing list