使用 C++ 的 DBus Glib:无法创建 DBusGProxy,释放它并再次创建它

Posted

技术标签:

【中文标题】使用 C++ 的 DBus Glib:无法创建 DBusGProxy,释放它并再次创建它【英文标题】:DBus Glib with C++: Can't create a DBusGProxy, release it and create that again 【发布时间】:2011-06-03 13:02:35 【问题描述】:

我正在开发一个在内部使用 Glib 连接到其他模块的库。

这个库有一个初始化方法来建立 dbus 连接和一个终止所有内部资源(包括 dbus 连接)的终止方法。 至少它应该这样做。

但是,在调用 terminate 方法后,我无法再次调用 dbus(当然,我在再次调用 dbus 方法之前再次调用了 initialize 方法)。

我主要使用 C++(一些用过的库在 C 中)。

这是我的内部 dbus 初始化程序:

#ifdef __cplusplus
extern "C" 
#endif

#include <dbus/dbus-glib.h>
#include <stdio.h>

#define _DBUS_SERVICE       "Removed due to restrictions"
#define _DBUS_PATH      "/"
#define _DBUS_INTERFACE "Removed due to restrictions"

static DBusGConnection * my_dbus_conn = NULL;
static DBusGProxy * my_proxy = NULL;

gboolean dbus_init() 
    GError *error = NULL;
    g_type_init();
    my_dbus_conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
    if (my_dbus_conn == NULL) 
        g_printerr("DBUS Connection Error (%s)\n", error->message);
        g_error_free(error);
        return false;
    
    my_proxy = dbus_g_proxy_new_for_name(my_dbus_conn, _DBUS_SERVICE, _DBUS_PATH, _DBUS_INTERFACE);
    if (my_proxy == NULL) 
        g_printerr("ERROR: DBUS Proxy creation Error (%s)\n", error->message);
        g_error_free(error);
        return false;
    
    return true;


DBusGProxy * dbus_get_proxy() 
    if (my_proxy == NULL) 
        dbus_init();
    
    return my_proxy;


void dbus_term() 
    g_object_unref(G_OBJECT (my_proxy));
    dbus_g_connection_unref(my_dbus_conn);
    my_dbus_conn = NULL;


#ifdef __cplusplus

#endif

这是我的调用代码:

MY_G_DEBUG("Manager", "Creating Server IPC stub...");
this->m_pDbusServer = get_proxy();

if (this->m_pDbusServer == NULL) 
    return;


MY_G_DEBUG("Manager", "CheckPoint 1!");
gboolean success;
GError *gerror = NULL;
char **l_pHelloWorldReply;

success = dbus_server_helloworld(this->m_pDbusServer, "Hello World from Manager", &l_pHelloWorldReply, &gerror);

MY_G_DEBUG("Manager", "CheckPoint 2!");

if (success == FALSE) 
    MY_G_DEBUG("Manager", "CheckPoint 3!");
    if (gerror == NULL) 
        MY_G_DEBUG("Manager", "CRITICAL: Hello World call Failed (error not set)");
     else 
        MY_G_DEBUG("Manager", "CRITICAL: Hello World call Failed (%s)", gerror->message);
        g_error_free(gerror);
        gerror = NULL;
    
    return;
 else 
    MY_G_DEBUG("Manager", "CheckPoint 4!");
    for (guint ii = 0; l_pHelloWorldReply[ii] != NULL; ii++) 
        MY_G_DEBUG("Manager", "Hello World response %d: %s", ii, l_pHelloWorldReply[ii]);
    


MY_G_DEBUG("Manager", "CheckPoint 5!");

这是日志输出:

(process:24498): Manager-DEBUG: Checkpoint: 1!
(process:24498): Manager-DEBUG: Checkpoint: 2!
(process:24498): Manager-DEBUG: Checkpoint: 3!
(process:24498): Manager-DEBUG: CRITICAL: Hello World call Failed (error not set)

我每次调用 dbus_term 函数时都会收到一条错误消息,但我无法修复它。

(process:24498): GLib-GObject-WARNING **: invalid uninstantiatable type `<invalid>' in cast to `GObject'
(process:24498): GLib-GObject-CRITICAL **: g_object_unref: assertion `G_IS_OBJECT (object)' failed

我第一次尝试调用方法时,一切正常... 我坚信这是由 dbus_term 问题引起的。

有人知道为什么会这样吗?

非常感谢。

【问题讨论】:

【参考方案1】:

删除对仍然打开的 dbus 连接的最后一个引用是一个错误。您使用的绑定的问题之一是很难知道连接何时真正关闭。这有点令人不满意,但我的习惯是在与会话总线等众所周知的总线的连接上留下一个参考。

【讨论】:

很高兴听到这个消息。我意识到这是不可能确定的。我现在正在迁移到 GDBus……我还使用套接字在进程之间进行一些通信。 GlibDBus 给我带来了很多麻烦。谢谢你的回答。 那么,解决办法是什么? 至少在我看来,这确实回答了这个问题。他的问题是这样的,“为什么我会收到这个错误?”我的回复告诉他,他遇到了一个错误,因为他写了一个错误,并进一步说明了这个错误是什么。澄清一下,我记得他对 dbus_term 的调用将会话总线上的引用计数变为 0,而 dbus 库仍在后台写入总线。这会使 dbus lib 的内部数据结构处于错误状态,因此下一次使用会话总线的尝试会失败。解决方案是在程序关闭之前保留一个对会话总线的引用。【参考方案2】:

不要在新代码中使用 dbus-glib,而是使用 GDBus。

GDBus 是 glib 2.26 中的新 dbus api。与 dbus-glib 相比,它的优势包括使用 GIO 异步模式(GAsync*、GCancellable)、将 GVariant 用于变体类型以及更好的线程支持。

看 http://library.gnome.org/devel/gio/2.28/ch29.html 用于迁移到 GDBus。

【讨论】:

我最近在 glibDbus 邮件列表中被告知。我正在处理这个 GDBus 迁移。非常感谢您的回答。 你没有回答问题。

以上是关于使用 C++ 的 DBus Glib:无法创建 DBusGProxy,释放它并再次创建它的主要内容,如果未能解决你的问题,请参考以下文章

DBus Glib 发送信号 - 没有发出信号

linux 进程间通信 dbus-glib实例详解一(附代码)(d-feet工具使用)

无法定位软件包dbus-glib-1

无法定位软件包dbus-glib-1

linux 进程间通信 dbus-glib实例详解二(上) 消息和消息总线(附代码)

DBus Glib,发送带有嵌套结构的信号