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