在线程中调用dbus-python

5 投票
2 回答
3651 浏览
提问于 2025-04-16 19:44

我在一个线程里调用dbus方法时遇到了段错误(segfault)。这是我的情况:我有一个程序叫Service1,它有一个方法叫test。还有一个程序叫Service2,它有一个方法叫expose。因为这个方法需要进行一些复杂的数学计算,所以我把一些参数从expose传递给一个正在运行的线程reader。这个线程在完成工作后,会调用Service1的test方法。但是在最后一次dbus调用时,我遇到了段错误。

代码如下:

# Service1.py
class Service1(Object):
    def __init__(self, bus):
        name = BusName('com.example.Service1', bus)
        path = '/'
       super(Service1, self).__init__(name, path)

    @method(dbus_interface='com.example.Service1',
        in_signature='s', out_signature='s')
    def test(self, test):
        print 'test being called'
        return test

dbus_loop = DBusGMainLoop()
dsession = SessionBus(mainloop=dbus_loop)
loop = gobject.MainLoop()
gobject.threads_init()

im = Service1(dsession)
loop.run()


# Service2.py
dbus_loop = DBusGMainLoop()
dsession = SessionBus(mainloop=dbus_loop)

class Service2(Object):
def __init__(self, bus):
    name = BusName('com.example.Service2', bus)
    super(Service2, self).__init__(name, '/')

    self.queue = Queue()
    self.db = bus.get_object('com.example.Service1', '/')
    self.dbi = dbus.Interface(self.db, dbus_interface='com.example.Service1')

@method(dbus_interface='com.example.Service2',
        in_signature='', out_signature='')
def expose(self):
    print 'calling expose'
    self.queue.put(('params',))

def reader(self):
    while True:
        val = self.queue.get()
        dd = self.dbi.test('test')
        print dd
        self.queue.task_done()


gobject.threads_init()
loop = gobject.MainLoop()

im = Service2(dsession)
reader = threading.Thread(target=im.reader)
reader.start()

loop.run()

要测试的话,先运行Service1.py和Service2.py,然后再运行这段代码:

dbus_loop = DBusGMainLoop()
session = SessionBus(mainloop=dbus_loop)
proxy = session.get_object('com.example.Service2', '/')
test_i = dbus.Interface(proxy, dbus_interface='com.example.Service2')
test_i.expose()

Service2.py在运行这段代码几次后应该会崩溃。但这是为什么呢?

2 个回答

3

Service1.py 文件中,试着在把 dbus_loop 赋值为 DBusGMainLoop() 之前,先调用一下 gobject.threads_init()

7

gobject.threads_init() 这个函数调用是不够的,你还需要调用 dbus.mainloop.glib.threads_init(),这样才能确保 dbus-glib 在多线程环境下是安全的。

撰写回答