g_bus_own_name连接总线失败
最近采用gdbus-codegen写了一组服务端和客户端,主要实现的功能是用服务端给客户端发送信号,但是在服务端中发现一个问题。
在虚拟机中测试正常,信号能够正常发送,但是在车机上运行时会一直阻塞。仔细梳理了一下代码逻辑后发现是阻塞在了sem_wait
处,这里信号量的作用是等待on_bus_acquired
函数调用(也就是连接上dbus总线后)完成后再发送信号。可是就是不能调用on_bus_acquired
函数,试了很多方法,最后发现是g_bus_own_name
函数形式少了一个参数,原来的代码是:
1 |
|
对比官网的参数原型,发现原代码中只有七个参数,而官方用法中有八个参数:
1 |
|
再仔细对比,发现少了name_lost_handler
这个回调函数,根据官网的说明,调用g_bus_own_name
函数有三个结果:
You are guaranteed that one of the name_acquired_handler and name_lost_handler callbacks will be invoked after calling this function there are three possible cases:
- name_lost_handler with a NULL connection (if a connection to the bus can t be made).
- bus_acquired_handler then name_lost_handler (if the name can t be obtained)
- bus_acquired_handler then name_acquired_handler (if the name was obtained).
于是对照官网重新写了g_bus_own_name
函数,结果发现是第一种情况,直接调用了name_lost_handler
这个函数,也就是没有连接上,所以也就不能够回调bus_acquired_handler
函数,所以一直在阻塞等待该函数完成时会陷入死循环。
阻塞的原因找到后,就要继续查找为什么会注册失败,最后发现是因为没有设置dbus的总线地址,导致连接失败。无论是gdbus,qdbus,还是commonapi等都是基于dbus的高级语言封装,他们在通信时都需要底层的dbus先准备好。而dbus在使用中需要设置bus address,这里可以设置一个环境变量:
1 |
|
再次测试代码,问题解决!
ps:
而且通过对官方接口的阅读,发现可以将发送信号操作放在name_acquired_handler
这个回调函数里面,因为这个函数会在bus_acquired_handler
函数完成后调用,这时候发送信号不会因为还没有连接上dbus总线而发送失败。