Signals in Python without glib
John (J5) Palmieri
johnp at redhat.com
Mon Jul 24 12:24:18 PDT 2006
The python bindings can not receive signals without the glib mainloop
and we don't currently wrap the methods needed to update and dispatch
(you need to update as well as dispatch). Patches welcome.
Justin Mazzola Paluska wrote:
> On Mon, Jul 24, 2006 at 12:56:28AM -0400, Havoc Pennington wrote:
>
>> If you don't have an existing main loop or don't need to block on
>> anything other than dbus, you don't need to do the main loop, you can
>> just use the blocking API on DBusConnection instead.
>>
>
> Does this apply for signals emitted too? I ask because there are
> things I only seem to be able to do by catching signals emitted by
> objects.
>
>
>> You could also use threads, though depending on your other code and your
>> experience with threads, that could be either harder or easier.
>>
>
> For our framework, using threads is par for the course, so using them
> is probably easiest -- the attached code uses them. The best solution
> (in Python, the language of our app) that I could come up with is
> attached [0].
>
> Essentially, what I do is start a thread that sits in a loop calling
> dispatch() on the connection, then sleep a little if there's nothing
> to do [1]. This seems to work OK, but has raised a few questions for
> me:
>
> 1. What do I have to worry about for thread safety? Can I still make
> blocking calls from other threads?
>
> 2. I don't get signals after a bit of time. If I run the glib
> eventloop, I can leave the program running for a while and still
> get signals from Avahi when new things come up and when things go
> down. After a few seconds, my solution seems to stop working.
>
> 3. I sniffed the message queue by putting the following code in my
> while loop:
>
> if dispatch_status == 0:
> print "dispatching" # -
> msg = con.borrow_message() # |
> print msg.get_type() # + The added code is here
> print msg.get_sender() # |
> con.return_message(msg) # _
> dispatch_status = con.dispatch()
>
> Most of the time msg.get_type() would give me message type 3,
> signal messages. However, sometimes I would get a message type 2
> (method return I think) and the code would segfault. It's likely
> that it's segfaulting because I haven't locked something when I
> should have, but it was learning code, so I chucked it.
>
> However, I still want to know how I should handle non-signal
> messages.
>
> I've read through
> http://dbus.freedesktop.org/doc/api/html/dbus-mainloop_8c-source.html
> for the dbus-mainloop.c source and it does far more than simple,
> brain-dead loop. However, I don't know how much more I need to
> implement.
>
> I'm worried most about problems 1 and 2, but they are probably related
> to problem 3.
>
> Thanks,
> --Justin
>
> [0] If you have Avahi's Python bindings installed, run it with:
>
> python2.4 service_type domain
>
> For example,
>
> python2.4 _workstation._tcp local
>
> should return the names of all of the workstations on your subnet.
>
> [1] I'd love to block on something rather than polling, but the
> set_dispatch_status_function function isn't available in the
> Python bindings in Debian Testing yet.
>
> ------------------------------------------------------------------------
>
> """ Low-level interface to mDNS and dns-sd through the Avahi Daemon."""
>
> # glib integration? http://www.j5live.com/?p=93
>
> __author__ = "Justin Mazzola Paluska"
>
> import dbus
> import avahi
> import threading
> import time
> from Queue import Queue
>
> # Use the python2.4 sets built-in if possible
> try:
> s = set()
> del s
> except NameError:
> from sets import Set as set
>
> system_bus = None
> avahi_proxy = None
> avahi_server = None
>
> def dispatch_loop():
>
> con = system_bus.get_connection()
> while True:
> dispatch_status = con.get_dispatch_status()
>
> if dispatch_status == 0:
> dispatch_status = con.dispatch()
> if dispatch_status == 1:
> # means there's no work to do right now, so sleep a
> # little.
> time.sleep(.001)
> elif dispatch_status == 2:
> #print "needs more memory?!?"
> time.sleep(.001)
>
>
> def init():
>
> global system_bus
> global avahi_proxy
> global avahi_server
>
> if system_bus:
> return
>
> system_bus = dbus.SystemBus()
> avahi_proxy = system_bus.get_object(avahi.DBUS_NAME,
> avahi.DBUS_PATH_SERVER)
> avahi_server = dbus.Interface(avahi_proxy,
> avahi.DBUS_INTERFACE_SERVER)
>
> th = threading.Thread(target=dispatch_loop)
> th.setDaemon(True)
> th.start()
>
> if __name__ == '__main__':
>
> import sys
>
> service_type = sys.argv[1]
> domain = sys.argv[2]
>
> init()
>
> service_browser_path = avahi_server.ServiceBrowserNew(
> avahi.IF_UNSPEC,
> avahi.PROTO_UNSPEC,
> service_type,
> domain,
> 0
> )
>
> sb_proxy = system_bus.get_object(avahi.DBUS_NAME,
> service_browser_path)
> sb_server = dbus.Interface(sb_proxy,
> avahi.DBUS_INTERFACE_SERVICE_BROWSER)
>
> # now the part where we need to use signals
> def _item_new_cb(interface,
> protocol,
> name,
> type,
> domain,
> flags):
>
> print "found", name
>
> sb_server.connect_to_signal('ItemNew',
> _item_new_cb)
>
> # now just sit in a loop while the results come in
> while True:
> time.sleep(1)
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> dbus mailing list
> dbus at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dbus
>
More information about the dbus
mailing list