Open*** v3 Dbus 客户端未接收到所有信号

Posted

技术标签:

【中文标题】Open*** v3 Dbus 客户端未接收到所有信号【英文标题】:Open*** v3 Dbus client not receiving all signals 【发布时间】:2021-09-20 00:52:47 【问题描述】:

我正在为 Linux Mint/Cinnamon 编写一个 Applet 来管理 Open*** v3 连接。

为了避免可能导致 DE 卡顿或冻结的同步调用,我正在使用 GJS 提供的 GioGLib 库编写一个简单的 DBus 客户端。这允许异步的、部分事件驱动的方法,并且应该避免任何令人讨厌的副作用。这是我第一次使用这些技术,但 Open*** DBus API 是 pretty well documented,Gio and GLib 的 API 文档也不错。

我遇到的问题是信号订阅,特别是net.open***.v3.sessions 服务发布的StatusChange 信号。每当建立、暂停、恢复或关闭连接时,都会发布一堆这些信号。大多数信号都是由我订阅的听众接收的,但不是全部。特别是,我没有收到session closed 信号。

使用dbus-monitor命令行工具,可以看到建立连接(7个信号)然后关闭(2个信号)时发布的所有StatusChange信号:

$ sudo dbus-monitor --system "type='signal',interface='net.open***.v3.sessions',member='StatusChange'"
...

// Connect:
signal time=1625847543.107244 sender=:1.891 -> destination=:1.892 serial=2745 path=/net/open***/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.open***.v3.sessions; member=StatusChange
   uint32 3
   uint32 27
   string "session_path=/net/open***/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49, backend_pid=42584"
signal time=1625847543.116395 sender=:1.891 -> destination=:1.892 serial=2762 path=/net/open***/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.open***.v3.sessions; member=StatusChange
   uint32 3
   uint32 17
   string "session_path=/net/open***/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49 backend_busname=net.open***.v3.backends.be42585 backend_path=/net/open***/v3/backends/session"
signal time=1625847543.117286 sender=:1.891 -> destination=(null destination) serial=2764 path=/net/open***/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.open***.v3.sessions; member=StatusChange
   uint32 2
   uint32 2
   string "config_path=/net/open***/v3/configuration/9dd3fa9cxb6e0x48acxaa1ex566312bea232"
signal time=1625847543.638519 sender=:1.891 -> destination=(null destination) serial=2775 path=/net/open***/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.open***.v3.sessions; member=StatusChange
   uint32 2
   uint32 2
   string "config_path=/net/open***/v3/configuration/9dd3fa9cxb6e0x48acxaa1ex566312bea232"
signal time=1625847543.638533 sender=:1.891 -> destination=(null destination) serial=2776 path=/net/open***/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.open***.v3.sessions; member=StatusChange
   uint32 2
   uint32 6
   string ""
signal time=1625847543.735357 sender=:1.891 -> destination=(null destination) serial=2777 path=/net/open***/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.open***.v3.sessions; member=StatusChange
   uint32 2
   uint32 6
   string ""
signal time=1625847543.974784 sender=:1.891 -> destination=(null destination) serial=2778 path=/net/open***/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.open***.v3.sessions; member=StatusChange
   uint32 2
   uint32 7
   string ""


// Disconnect:
signal time=1625847646.846790 sender=:1.891 -> destination=:1.892 serial=2834 path=/net/open***/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.open***.v3.sessions; member=StatusChange
   uint32 3
   uint32 28
   string "Session closed"
signal time=1625847646.848262 sender=:1.891 -> destination=:1.892 serial=2839 path=/net/open***/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49; interface=net.open***.v3.sessions; member=StatusChange
   uint32 3
   uint32 19
   string ""

以下代码创建了一个订阅,据我所知,它应该接收与上述相同的信号。注意我在这里使用较低级别的方法来获取订阅;订阅是在全局连接上进行的,而不是通过特定对象路径的 DBusProxy。我已经尝试了这两种方法(结果相同),但以下应该更类似于上面的dbus-monitor 命令。

    subscribeToStatusChangeSignals() 
        this.statusChangeHandlerId = Gio.DBus.system.signal_subscribe(
            'net.open***.v3.sessions',
            'net.open***.v3.sessions',
            'StatusChange',
            null,
            null,
            Gio.DBusSignalFlags.NONE,
            this._handleGlobalStatusChangeSignal
        );
    

    _handleGlobalStatusChangeSignal(connection, sender, path, iface, signal, params) 
        let container = params.deep_unpack();
        let statusMajorCode = container[0];
        let statusMinorCode = container[1];
        let statusMajor = lookupStatusMajor(statusMajorCode);  // lookup the corresponding text
        let statusMinor = lookupStatusMinor(statusMinorCode);  // from something resembling an enum
        let message = container[2];

        global.log(`Received StatusChange signal
            path:         [$path]
            Status Major: [$statusMajorCode - $statusMajor]
            Status Minor: [$statusMinorCode - $statusMinor]
            Message:      [$message]`
        );
    

打开和关闭同一个连接时产生的日志:

// Connect:
Cjs-Message: 18:19:03.117: JS LOG: [LookingGlass/info] Received StatusChange signal
            path:         [/net/open***/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49]
            Status Major: [2 - CONNECTION]
            Status Minor: [2 - CFG_OK]
            Message:      [config_path=/net/open***/v3/configuration/9dd3fa9cxb6e0x48acxaa1ex566312bea232]
Cjs-Message: 18:19:03.638: JS LOG: [LookingGlass/info] Received StatusChange signal
            path:         [/net/open***/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49]
            Status Major: [2 - CONNECTION]
            Status Minor: [2 - CFG_OK]
            Message:      [config_path=/net/open***/v3/configuration/9dd3fa9cxb6e0x48acxaa1ex566312bea232]
Cjs-Message: 18:19:03.639: JS LOG: [LookingGlass/info] Received StatusChange signal
            path:         [/net/open***/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49]
            Status Major: [2 - CONNECTION]
            Status Minor: [6 - CONN_CONNECTING]
            Message:      []
Cjs-Message: 18:19:03.735: JS LOG: [LookingGlass/info] Received StatusChange signal
            path:         [/net/open***/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49]
            Status Major: [2 - CONNECTION]
            Status Minor: [6 - CONN_CONNECTING]
            Message:      []
Cjs-Message: 18:19:03.974: JS LOG: [LookingGlass/info] Received StatusChange signal
            path:         [/net/open***/v3/sessions/052850e7s915fs483esb3e7s3afb389a2e49]
            Status Major: [2 - CONNECTION]
            Status Minor: [7 - CONN_CONNECTED]
            Message:      []

// Disconnect:
<nada>

我注意到的一个模式是,我收到的所有信号在dbus-monitor 输出中都有一个null destination

... sender=:1.891 -> destination=(null destination) ...

虽然我没有收到的信号有特定的目的地:

... sender=:1.891 -> destination=:1.892 ...

大概这些是针对特定接收者的直接信号,而不是向所有感兴趣的订阅者广播的信号,但我在文档中的任何地方都没有发现这一点。

所以问题是,为什么我会收到一些信号,但不是全部?这是设计使然,还是Gio 的问题,或者(更有可能)是我使用它的问题?

【问题讨论】:

【参考方案1】:

经过进一步挖掘,这种行为似乎是设计使然——携带目标值的信号被视为单播消息。预定收件人以外的订阅者只有在配置为eavesdrop 时才会收到此类消息。 dbus-monitor 大概就是这种情况。

来源:DBus Specification (Message Routing)

【讨论】:

以上是关于Open*** v3 Dbus 客户端未接收到所有信号的主要内容,如果未能解决你的问题,请参考以下文章

Android 到 Linux 蓝牙未找到所有 UUID

XMLHttpRequest对象有几个返回状态值?Servlet与JSP的关系

dbus - 未定义的引用

客户端未使用 websockets 接收所有消息

socket.io 客户端未从服务器接收消息

用python接收dbus信号