Python <--> d-bus <--> c++ woes

Simon McVittie simon.mcvittie at collabora.co.uk
Mon Mar 4 04:12:58 PST 2013


On 01/03/13 02:20, Kip Warner wrote:
> All of this happens via simple signals with no
> need for advanced methods.

Adding some not-very-advanced method calls would make your code work
considerably better :-)

Note that the reference D-Bus implementation in libdbus is really very
low-level. If you like GLib (which it seems you use in your Python code
already), please look at GDBus (part of GIO since 2.26), which does a
lot more of the hard work for you.

You could also use GDBus in your Python code (via "from gi.repository
import Gio") as an alternative to dbus-python ("import dbus"): then
you'd be using the same nice GObject-based D-Bus binding in both
modules, albeit via different languages.

> Next the C++ application is invoked.

I would advise you to look into D-Bus service activation: the technique
used by things like Telepathy and gnome-terminal (among many, many
others) to get services started automatically when a D-Bus client calls
one of their methods. The short version is "write a .service file, then
when your service starts, request the corresponding well-known name".

For instance <http://www.freedesktop.org/wiki/IntroductionToDBus> and
<http://raphael.slinckx.net/blog/documents/dbus-tutorial> both reference
service activation.

> Next the Python application attempts to connect to the C++ application's
> d-bus service. The Python application keeps trying (loop at line 82)
> until it succeeds. It then emits the "Ready" signal (line 122):
>         
>         <https://bazaar.launchpad.net/~avaneya/avaneya/trunk/view/head:/Extras/Viking%20Lander%20Remastered/Launcher/Source/RecoveryPage.py#L68>

I think the C++ application should implement a method, and the Python
application should call it. To avoid race conditions you might need two
methods: call one to activate the C++ application, then connect to its
signals, then call another method to say "OK I've connected my signal
handlers, you're good to go".

> It awaits by blocking
> until this "Ready" signal sent by the Python application is received
> (line 242) before it does the actual work it needs to do:
>         
>         <https://bazaar.launchpad.net/~avaneya/avaneya/trunk/view/head:/Extras/Viking%20Lander%20Remastered/Extractor/Source/DBusInterface.cpp#L242>

Use GDBus. Seriously. :-)

Failing that, it would be more conventional to use a main loop (e.g. the
GLib one via dbus-glib), or to register a "filter function" to receive
messages then call dbus_connection_read_write_dispatch() to "turn the
handle" on the D-Bus connection.

> As mentioned earlier, the problem is the "Ready" signal sometimes isn't
> received in the C++ application's blocking method that waits for it, and
> sometimes even when it is received, I notice there is a delay of upwards
> of 20 seconds or more.

If you used a method call instead of a signal, and made the C++ part
send a reply to that method call when it processes it, then the Python
code would always get a reply: either an error from the dbus-daemon,
essentially saying "the C++ part isn't running", or a successful reply
from the C++ part. This would make it easier to diagnose what's going on.

I don't immediately see why you get a 20 second delay or message loss.

    S


More information about the dbus mailing list