Signals in Python without glib
Havoc Pennington
hp at redhat.com
Mon Jul 24 10:51:14 PDT 2006
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.
Signals and methods are all the same from a mainloop point of view, they
are just messages to be dispatched.
> 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].
Rather than sleeping, you should simply block. The simplest loop (in C) is:
while (dbus_connection_read_write_dispatch(connection, -1))
;
This will dispatch if there's stuff to dispatch, otherwise block.
> 1. What do I have to worry about for thread safety? Can I still make
> blocking calls from other threads?
libdbus is supposed to support using the same connection from multiple
threads, but there are issues with that right now (see the patch I
posted last Friday). So you'd probably end up fixing some bugs in
libdbus if you used the same connection from multiple 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.
No guesses, just some bug I imagine. dbus verbose mode might help (set
DBUS_VERBOSE=1 in the environment)
> 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.
Could be a bug in libdbus, I don't think the borrow/return stuff has
been heavily used by anyone.
> However, I still want to know how I should handle non-signal
> messages.
All messages should work the same way ... there's just a single message
queue.
> 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.
If you are happy to just block, then I think dbus-monitor.c for example
does the while (read_write_dispatch) thing.
Havoc
More information about the dbus
mailing list