GDBusProxy missing bus signals during construction



I am trying to implement a Zeroconf service browser using a PyGobject Gio.DBusProxy object to talk to avahi. It all works fine but the browser randomly misses the initial one or more ItemNew signals from the avahi server. It sometimes even misses the AllForNow signal. Subsequent ItemNew signals are seen OK as services come and go.

It appears that the problem is that the GLIb objects subscribes to the dbus signals during the construction process (the DO_NOT_CONNECT_SIGNALS is not set). It then notifies(GDbusProxy.new) or returns(GDBusProxy.new_sync) to the calling object. Once I get the new proxy object back I can use connect on the parent gobject to hook the incoming dbus signal to my applications signal handling callback. However any dbus signals that arrive from server (avahi) before that connection is made are discarded. If set DO_NOT_CONNECT_SIGNALS I would have mimic the whole of DBusProxy/DBUsConection's handling of dbus side signal mapping. I don't want to have to do that. What am I missing?

Some fundamental questions are.

1. How can I stop this happening.
2. Is avahi breaking some sort of dbus protocol or convention in sending these signals immediately a new bus connection is made? 3. Is the a flaw in the GDBusProxy design/documenation? (sorry guys, but have spent a while looing at this.)

Thanks,

Roger

Here is my python code

#!/usr/bin/env python
from gi.repository import Gio, GLib, GObject, Gtk
import avahi
import signal
import time

class avahibrowser(Gio.Application):
    def service_resolved(self, *args):
        print 'service resolved'
        print 'name:', args[2]
        print 'address:', args[7]
        print 'port:', args[8]

    def print_error(self, *args):
        print 'error_handler'
        print args[0]

    def browserCallback(self, proxy, sender, signal, args):
        if signal == 'ItemNew':
            # Arguments are [0] i interface, [1] i protocol [2] s name [3] s type  [4] s domain [5] u flags
            print "Found service '%s' type '%s' domain '%s' " % (args[2], args[3], args[4])
            #self.avahiserver.ResolveService('iisssiu',
            #    args[0], # Interface
            #    args[1], # Protocol
            #    args[2], # Name
            #    args[3], # Service Type
            #    args[4], # Domain
            #    avahi.PROTO_UNSPEC, dbus.UInt32(0),
            #    reply_handler=self.service_resolved, error_handler=self.print_error)
        else:
            print 'signal', signal, 'arguments', args
def do_activate(self): # Define this to suppress glib warning
        pass
def new_browser_proxy_callback(self, source_object, res, user_data):
        #source_object.connect('g-signal', self.browserCallback)
        self.avahibrowser = Gio.DBusProxy.new_finish(res)
        self.avahibrowser.connect('g-signal', self.browserCallback)
def new_server_proxy_callback(self, source_object, res, user_data):
        self.avahiserver = Gio.DBusProxy.new_finish(res)
        avahibrowserpath = self.avahiserver.ServiceBrowserNew('(iissu)',
                                avahi.IF_UNSPEC,
                                avahi.PROTO_INET,
                                '_scratch._tcp',
                                'local',
                                0)

Gio.DBusProxy.new(self.systemDBusConnection, 0, None,
                                            avahi.DBUS_NAME,
                                            avahibrowserpath,
                                            avahi.DBUS_INTERFACE_SERVICE_BROWSER, None,
                                            self.new_browser_proxy_callback, None)
def bus_get_callback(self, source_object, res, user_data):
        self.systemDBusConnection = Gio.bus_get_finish(res)
Gio.DBusProxy.new(self.systemDBusConnection, 0, None,
                                            avahi.DBUS_NAME,
                                            avahi.DBUS_PATH_SERVER,
                                            avahi.DBUS_INTERFACE_SERVER, None,
                                            self.new_server_proxy_callback, None)
# Gnome application initialization routine
    def __init__(self, application_id, flags):
        Gio.Application.__init__(self, application_id=application_id, flags=flags)
Gio.bus_get(Gio.BusType.SYSTEM, None, self.bus_get_callback, None) def InitSignal(app):
    def signal_action(signal):
        if signal is 1:
            print("Caught signal SIGHUP(1)")
        elif signal is 2:
            print("Caught signal SIGINT(2)")
        elif signal is 15:
            print("Caught signal SIGTERM(15)")
        app.release()

    def idle_handler(*args):
        print("Python signal handler activated.")
        GLib.idle_add(signal_action, priority=GLib.PRIORITY_HIGH)

    def handler(*args):
        print("GLib signal handler activated.")
        signal_action(args[0])

    def install_glib_handler(sig):
        unix_signal_add = None

        if hasattr(GLib, "unix_signal_add"):
            unix_signal_add = GLib.unix_signal_add
        elif hasattr(GLib, "unix_signal_add_full"):
            unix_signal_add = GLib.unix_signal_add_full

        if unix_signal_add:
            print("Register GLib signal handler: %r" % sig)
            unix_signal_add(GLib.PRIORITY_HIGH, sig, handler, sig)
        else:
            print("Can't install GLib signal handler, too old gi.")

    SIGS = [getattr(signal, s, None) for s in "SIGINT SIGTERM SIGHUP".split()]
    for sig in filter(None, SIGS):
        print("Register Python signal handler: %r" % sig)
        signal.signal(sig, idle_handler)
        GLib.idle_add(install_glib_handler, sig, priority=GLib.PRIORITY_HIGH)

if __name__ == "__main__":
    Application = avahibrowser("uk.co.beardandsandals.avahibrowser", Gio.ApplicationFlags.FLAGS_NONE)
# Set up python and Gio signal handling
    InitSignal(Application)
Application.hold()

    Application.run(None)
print 'Exiting'



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