版权声明:本文为博主原创文章,未经博主允许不得转载。

最近采用gdbus-codegen写了一组服务端和客户端,主要实现的功能是用服务端给客户端发送信号,但是在服务端中发现一个问题。

 在虚拟机中测试正常,信号能够正常发送,但是在车机上运行时会一直阻塞。仔细梳理了一下代码逻辑后发现是阻塞在了sem_wait处,这里信号量的作用是等待on_bus_acquired函数调用(也就是连接上dbus总线后)完成后再发送信号。可是就是不能调用on_bus_acquired函数,试了很多方法,最后发现是g_bus_own_name函数形式少了一个参数,原来的代码是:
owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, //bus_type
                           "com.hangsheng.UPDATE.InformServer", //bus_name
                           G_BUS_NAME_OWNER_FLAGS_NONE, //flag
                           on_bus_acquired, //注册输出对象的回调函数
                           NULL,
                           NULL,
                           NULL);
对比官网的参数原型,发现原代码中只有七个参数,而官方用法中有八个参数:
guint g_bus_own_name (GBusType bus_type, const gchar *name,
                      GBusNameOwnerFlags flags,
                      GBusAcquiredCallback bus_acquired_handler,
                      GBusNameAcquiredCallback name_acquired_handler,
                      GBusNameLostCallback name_lost_handler,
                      gpointer user_data,
                      GDestroyNotify user_data_free_func);
再仔细对比,发现少了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,这里可以设置一个环境变量:
export DBUS_SESSION_BUS_ADDRESS= unix:path=/run/dbus/session_bus_help
再次测试代码,问题解决!
ps:
而且通过对官方接口的阅读,发现可以将发送信号操作放在name_acquired_handler这个回调函数里面,因为这个函数会在bus_acquired_handler函数完成后调用,这时候发送信号不会因为还没有连接上dbus总线而发送失败。
g_bus_own_name连接总线失败
Tagged on:

发表评论

邮箱地址不会被公开。 必填项已用*标注