Python cannot work as dbus server and client in the multi-thread enviroment -
i created dbus server following code, named server1.py
#!/usr/bin/python2.7 import dbus.service import dbus.glib import glib import gobject dbus.mainloop.glib import dbusgmainloop class app_server(dbus.service.object): def __init__(self): bus = dbus.sessionbus(private = true, mainloop = dbusgmainloop()) bus_name = dbus.service.busname('de.test.app1', bus) dbus.service.object.__init__(self, bus_name, '/de/test/app1_obj_path') @dbus.service.method("test.app1.interface",) def is_ready(self): return true def publish_dbus(): loop = glib.mainloop() app_server() loop.run() if __name__ == '__main__': gobject.threads_init() dbus.glib.init_threads() publish_dbus()
and want access dbus service in server1.py following code, named server2.py work dbus server.
#!/usr/bin/python2.7 import dbus.service import dbus.glib import glib import dbus.mainloop import gobject dbus.mainloop.glib import dbusgmainloop threading import thread time import sleep class app_server(dbus.service.object): def __init__(self): bus = dbus.sessionbus(private = true, mainloop = dbusgmainloop()) bus_name = dbus.service.busname('de.test.app3', bus) dbus.service.object.__init__(self, bus_name, '/de/test/app3_obj_path') @dbus.service.method("test.app3.interface",) def is_ready(self): return true def call_dbus(): bus_name = 'de.test.app1' obj_path = '/de/test/app1_obj_path' interface_name = 'test.app1.interface' count = 1 while count < 1000: proxy_bus = dbus.sessionbus(private = true) obj = none try: obj = proxy_bus.get_object(bus_name, obj_path) except: sleep(1) obj = proxy_bus.get_object(bus_name, obj_path) ready = obj.get_dbus_method('is_ready', interface_name) ready(pid_, bin_path) count += 1 print count def publish_dbus(): loop = glib.mainloop() app_server() loop.run() if __name__ == '__main__': gobject.threads_init() dbus.glib.init_threads() th1 = thread(target = publish_dbus) th1.start() th2 = thread(target = call_dbus) th2.start() sleep(10000000)
then after run server2.py, application terminated without finished dbus call in thread "call_dbus".
and if tried follwoing code, changed code in server2.py following:
from:
proxy_bus = dbus.sessionbus(private = true)
to:
proxy_bus = dbus.sessionbus(private = true, mainloop = dbus.mainloop.null_main_loop)
now, there have many connnections after thread "callbus" finished using tools "d-feet" can used d-bus debugger check if dbus server ready or if dbus connection has been established.
if can make suggeston make work normally??
what i've noticed this:
- your bus/object names don't match.
- you create new dbus connection each time in while loop. bad idea, specially seen don't close them.
either move call out of loop, or use shared connection (private=false
) - you don't need own thread publish dbus object, that's mainloop anyway.
- if run mainloop in different thread, make sure have way stop, otherwise
kill
way of terminating program. or put int in main thread, should @ least react ctrl-c - the sleep @ end of program unnecessary. long there running non-daemon threads around program won't exit anyway.
putting together, should work:
#!/usr/bin/python2.7 import dbus.service import dbus.glib import glib import dbus.mainloop import gobject dbus.mainloop.glib import dbusgmainloop threading import thread time import sleep class app_server(dbus.service.object): def __init__(self): bus = dbus.sessionbus(private = true, mainloop = dbusgmainloop()) bus_name = dbus.service.busname('de.test.app3', bus) dbus.service.object.__init__(self, bus_name, '/de/test/app3_obj_path') @dbus.service.method("test.app3.interface",) def is_ready(self): return true def call_dbus(): bus_name = 'de.test.app3' obj_path = '/de/test/app3_obj_path' interface_name = 'test.app3.interface' proxy_bus = dbus.sessionbus(private = true) count = 1 while count < 1000: obj = none try: obj = proxy_bus.get_object(bus_name, obj_path) except: sleep(1) obj = proxy_bus.get_object(bus_name, obj_path) ready = obj.get_dbus_method('is_ready', interface_name) #ready(pid_, bin_path) count += 1 print count if __name__ == '__main__': gobject.threads_init() dbus.glib.init_threads() loop = glib.mainloop() server = app_server() #th1 = thread(target = publish_dbus) #th1.start() th2 = thread(target = call_dbus) th2.start() loop.run()