Re: Synchronous method in asynchronous signal callback

Simon McVittie <simon.mcvittie-ZGY8ohtN/[email protected]>
Newsgroups gmane.comp.freedesktop.dbus
Organization Collabora Ltd.
Message-ID <[email protected]>
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/>

_______________________________________________
dbus mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dbus
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.