[dbus][python] Method dispatch also single-threaded?
John (J5) Palmieri
johnp at redhat.com
Mon Jan 22 14:33:24 PST 2007
On Mon, 2007-01-22 at 15:12 -0600, tsuraan wrote:
> Is it possible for a single dbus-python exported object to dispatch
> multiple methods at once? I have one object that exports a few (slow)
> methods, and in another program I quickly call them (asynchronously).
> The slow object is printing at the beginning and end of each method
> call, so it's clear that the methods aren't being run simultaneously.
> Instead, each waits for the one before it to finish. Is there some
> way to get the mainloop to dispatch methods simultaneously?
>
> Also, to make sure there wasn't a bug in the async calls, I tried
> doing all three methods at once in different instances of python, and
> I get the same problem. "Screenshot" follows:
>
> tsuraan at localhost ~/test/python/dbus/moreblocking $ cat Slow.py
> import gobject
> import dbus
> import dbus.service
> import dbus.glib
> import time
>
> class Slow(dbus.service.Object):
> def __init__(self):
> bus = dbus.SystemBus ()
> bus_name = dbus.service.BusName("com.example.Slow", bus)
>
> super(Slow, self).__init__(bus_name, "/Object")
>
> @dbus.service.method("com.example.Slow")
> def function1(self):
> print 'starting function1'
> time.sleep(5)
> print 'done with function1'
> return 1
>
> @dbus.service.method("com.example.Slow")
> def function2(self):
> print 'starting function2'
> time.sleep(5)
> print 'done with function2'
> return 2
>
> @dbus.service.method("com.example.Slow")
> def function3(self):
> print 'starting function3'
> time.sleep (5)
> print 'done with function3'
> return 3
>
>
> if __name__ == "__main__":
> gobject.threads_init()
> dbus.glib.init_threads()
>
> s = Slow()
> gobject.MainLoop().run()
>
> tsuraan at localhost ~/test/python/dbus/moreblocking $ cat test.py
> import gobject
> import dbus
> import dbus.glib
> import time
>
> def noop(*args):
> pass
>
> bus = dbus.SystemBus()
> obj = bus.get_object ("com.example.Slow", "/Object")
> obj.function1(reply_handler=noop, error_handler=noop)
> obj.function2(reply_handler=noop, error_handler=noop)
> obj.function3(reply_handler=noop, error_handler=noop)
>
> gobject.MainLoop().run()
>
> tsuraan at localhost ~/test/python/dbus/moreblocking $ python Slow.py &
> sleep 1 && python test.py
> [1] 18460
> starting function1
> done with function1
> starting function2
> done with function2
> starting function3
> done with function3
Well if your service object isn't returning to the mainloop or starting
up a thread it isn't going to process the next call until it is done
with the first call. Async calls only have to do with making sure the
client doesn't block. If you don't want your server to block on long
running calls you need to return to the mainloop sooner than later. It
is the same issue as with gui blocking. If you call a function which
doesn't return to the mainloop your application's gui doesn't respond.
You need to either run your calculations in a thread or defer sending a
reply and doing your calculations in an idle handler. Remember though,
you have around 25 seconds to get an answer back to the client if it
uses the default timeout.
--
John (J5) Palmieri <johnp at redhat.com>
More information about the dbus
mailing list