signals are not received when using inner mainloop
Submitted by Martin Pitt
Assigned to Simon McVittie
Description
Created attachment 17629 reproducer
I have a D-BUS service (Jockey, https://launchpad.net/jockey in my case) with some methods which require to consult PackageKit. This is a bit tricky, since PackageKit is fully asynchrous and only delivers actual results over D-BUS signals. Thus, for actually delivering an answer, my D-BUS service method has to do the PackageKit call, set up a private gobject.MainLoop() and a signal handler (for "Finished"), and have that signal handler quit the main loop.
The problem is that while the inner main loop is running, signals are never received. They are transported over the bus (they appear in dbus-monitor), but my program never catches them. Interestingly, when I press Control-C, the inner MainLoop reacts, and all signals are flushed and their handlers called.
I don't think that using two main loops is the problem. I tried re-using the MainLoop of the D-BUS service itself, and used a "while not flag_set_by_signal_handler: do a main loop iteration" loop, with the same result: the iteration just blocks forever.
I wrote a small reproducer to illustrate the problem, based on the official D-BUS python examples. It's best to use three consoles:
con1$ python dbus-hang.py -> run the server
con2$ dbus-send --dest=com.example.SampleService --type=signal /SomeObject com.example.SampleInterface.Poke -> this signal is properly caught, and the signal handler triggers; this happens while no service method is running, i. e. in the outside main loop.
con3$ dbus-send --dest=com.example.SampleService --print-reply /SomeObject com.example.SampleInterface.HelloWorld string:moo -> call HelloWorld(), which will wait for a "Poke" signal in order to finish
con2$ dbus-send --dest=com.example.SampleService --type=signal /SomeObject com.example.SampleInterface.Poke -> Signal is sent, but never received by dbus-hang.py; press Control-C, and it is received
This only seems to affect signals. I can call D-BUS methods just fine while being in a D-BUS service method (e. g. I can get a PackageKit transaction ID, or query PolicyKit).
If this is not the right way to do it, I'd appreciate some guidance how to solve this problem differently. I have wrapped my head around this problem for days, and was just banging my head on the table.
Many thanks in advance for any help!
Martin
Attachment 17629, "reproducer":
dbus-hang.py