我有一个用 vala 编写的应用程序,它使用 dbus-daemon 与另一个进程(用 vala 编写)进行通信。效果很好。但dbus-daemon重启后就通讯失败了
我的应用程序(未重新启动)在 dbus 守护进程重新启动后尝试重新连接到 dbus 守护进程。我的应用程序区域内有 dbus 连接引用的清理代码。但 GTK.Application 会启动 dbus 连接供其使用。 dbus 守护进程终止后,这不会被清除。
由于 GTK.Application 中 dbus-connection 的引用未清除,因此故障转移后返回的 dbus-connection 保持不变,并且对于 dbus 操作返回“连接已关闭”错误。
有没有办法在 GTK.Application 代码中进行清理(基本上删除 dbus-connection 的引用)? 或者有人尝试在启动期间排除 GTK.Application 代码中的 dbus 连接启动?
在调试过程中,我尝试了以下操作。
我尝试取消引用 dbus 连接 4-5 次(在我的 dbus 清理代码中),然后重新连接到 dbus 守护进程就可以了。这意味着 dbus 连接正在其他区域使用(我假设是 GTK.Application 代码),并且在 dbus 守护进程终止后它没有被正确清理。当我在清理代码中执行 unref (出于调试目的)4-5 次,然后如果我停止应用程序,则会导致 GTK.Application 代码区域中出现分段错误(这可以解释为 dbus- 的陈旧内存指针) GTK.应用程序代码中仍在使用连接。
可能可以优雅地处理 D-Bus 代理/守护进程的重新启动。看起来也很难,没有人做,所以你会遇到困难。
Systemd 处理总线的重启,但它使用 sd-bus 而不是 GDBus。
您可能需要做的是,每个人都取消引用
GDBusConnection
并使之前 D-Bus 会话中的所有状态无效。如果您使用 g_bus_get()
中的单例,请确保所有用户也取消引用它。您可能使用的库也使用 g_bus_get()
,因此它们也需要放弃引用(并且可能这些库也必须明智地处理重新启动)。如果您使用自己的 GDBusConnection
实例(而不是 g_bus_get()
中的实例),可能会更简单。然后轮询以重新连接到总线。
但也许只是不这样做。
D-Bus 为您提供诸多优势,例如定义的消息排序和可靠的传输。如果您假设您的 D-Bus 连接被破坏(因为守护进程重新启动)并添加代码来处理该问题,那么这会增加您的复杂性。
它还要求您为通常不会发生并且可能没有经过充分测试的事情添加重要的代码。
相反。没做什么。无论谁重新启动 D-Bus 守护程序,也应该重新启动您的应用程序。事实上,大多数D-Bus服务也不能很好地处理重启,因此这些服务也需要重新启动。到那时,他们不妨重新启动机器。
除了看到各种事情被破坏之外,也没有什么理由重新启动 D-Bus 守护进程。只是不要这样做,或者如果这样做,请重新启动机器。
如果有的话,那么 dbus-broker/dbus-daemon 应该实现无缝重启,这样并非所有客户端都需要重新实现这一点。但没有人实现这一点,所以它显然并不像一些人想象的那么重要(https://github.com/bus1/dbus-broker/issues/93)。这一领域的工作将使每个人受益,这与每个试图自己处理这个问题的 D-Bus 客户相反。