Re: GDBusProxy missing bus signals during construction

On 23/07/15 21:59, Roger James wrote:
The "AvahiServer" object (proxy) is responding to the call to it's
ServiceBrowserNew method  by sending back the 'path' you should connect
to and create an "AvahiServiceBrowser" proxy object  on. This is
immediately followed by a broadcast of the 'catch up' information.

If there is no accompanying method call that you can use to catch up,
then I consider that to be bad (or at least unconventional) D-Bus API
design in Avahi. A well-designed D-Bus API will typically have a
separate method call that you can use to catch up ("state recovery").

A couple of examples: in the standard D-Bus Properties interface, you
connect to the PropertiesChanged signal, and then call the Get() or
GetAll() method to catch up on what you missed; in Telepathy instant
messaging channels, you might connect to the ReceivedMessage signal,
then call ListMessages() to catch up.

Avahi is a relatively early D-Bus service, so it is not necessarily
unexpected if it does not follow design conventions that were developed
later, like the importance of state-recovery.

I propose to get this by round this by subscribing to the Avahi ItemNew
signal  on my "AvahiServer"  proxy to catch the updates and then
unscribing it after I have connected the gobject signal on the
'AvahiServiceBrowser' proxy.

org.freedesktop.Avahi.Server does not appear to have an ItemNew signal.
I would recommend dropping down to a lower-level API than proxy objects:
using Gio.DBusConnection.signal_subscribe() to match ItemNew signals at
*any* object path (use None for the object path parameter).

If you're going to subscribe to ItemNew in advance, you might as well
ignore the GObject signal from the Gio.DBusProxy (indeed, use
Gio.DBusProxyFlags.DO_NOT_CONNECT_SIGNALS to suppress it), and continue
to use your existing subscription to ItemNew; simpler to have one code
path than two, even if that one code path is not the one you would have
used with a more conventionally-designed service.

Other than that, yes, this is a correct and necessary workaround for
services that don't have proper state-recovery.

Higher-level APIs like Gio.DBusProxy only work for service designs that
follow the necessary conventions so that they *can* work. For unusual
D-Bus service designs, Gio.DBusConnection.signal_subscribe() and provide a parallel, lower-level API, as well
as being the building blocks that were used to implement Gio.DBusProxy.

I have no idea how that will play in the heavily multi-threaded 
enviroment this is eventually to be deployed in.

As documented in the API reference, Gio.DBusConnection.signal_subscribe
callbacks are called in the main-context that was the thread-default
main context at the time signal_subscribe() was called. More on that
topic here:

This means you probably want one signal_subscribe() per main-context
(approximately: one per thread), with each callback ignoring any object
paths that are not relevant to that thread.

Simon McVittie
Collabora Ltd. <>

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]