我写了一个python D-Bus监控工具,它应该接收会话总线上的所有消息。 问题是如果短时间内有多条消息(信号,方法调用,方法返回),我只会收到第一个消息。我用dbus-monitor测试了这个,它显示了总线上的所有消息。
这是我的剧本:
import sys
import os
import time
import dbus
import dbus.service
import _dbus_bindings
import gobject
# This creates a GLib main context which is later used by a GLib mainloop to process events that dbus-python associates with that context.
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
def print_message(m):
print(m)
class Input:
def start(self):
pass
def run(self):
#print "Input=", self.__class__
self.start()
self.out.start()
self.run_inner()
self.out.stop()
self.stop()
def run_inner(self):
pass
def stop(self):
pass
class Output:
def start(self):
pass
def message_dictionary_handler(self, message_dictionary):
pass
def stop(self):
pass
class Handler(Output):
def __init__(self, message_dictionary_handler):
"""message_dictionary_handler: callable"""
self.message_dictionary_handler = message_dictionary_handler
class Monitor(Input):
def __init__(self, which_bus, out):
"""which_bus: "system" or "session"
out: Output"""
if which_bus == "system":
self.bus = dbus.SystemBus()
else:
self.bus = dbus.SessionBus()
self.out = out
def start(self):
"""
Start monitoring the bus
"""
# Arrange for this application to receive all messages on the bus.
self.bus.add_match_string("eavesdrop='true'")
# Add message filter. Filter are handlers that are run on all incoming messages.
self.bus.add_message_filter(self.msg_filter)
def stop(self):
"""
Stop monitoring the bus
"""
# Remove message filter
self.bus.remove_message_filter(self.msg_filter)
# Remove string matching
self.bus.remove_match_string("eavesdrop='true'")
def message_dictionary_maker(self, m):
"""
m: received message
"""
dump=m
return dump
def msg_filter(self, abus, msg):
"""
abus: bus session
msg: received message
"""
message_dictionary = self.message_dictionary_maker(msg)
self.out.message_dictionary_handler(message_dictionary)
def run_inner(self):
loop = gobject.MainLoop()
print("Press Ctrl-C to stop.")
try:
loop.run()
except:
print(" Loop exited")
def reset(self):
pass
out = Handler(print_message)
input = Monitor("session", out)
input.run()
来自我的监视器的消息:
dbus.lowlevel.**MethodCall**Message path: /com/mydbus/pydbus/clientserver, iface: com.mydbus.pydbus.clientserver, member: Data dest: com.mydbus.pydbus.clientserver
dbus.lowlevel.**MethodRetur**nMessage object at 0x76d582e0
dbus.lowlevel.**Signa**lMessage path: /org/freedesktop/DBus, iface: org.freedesktop.DBus, member: NameOwnerChanged, dest: (broadcast)
来自dbus-monitor的消息:
**method call** time=1507725081.508751 sender=:1.34 -> destination=com.mydbus.pydbus.clientserver serial=3 path=/com/mydbus/pydbus/clientserver; interface=com.mydbus.pydbus.clientserver; member=Data
string "HelloDBUSServerThisIsClient1"
**method return** time=1507725082.511337 sender=:1.31 -> destination=:1.34 serial=7 reply_serial=3
string "Return von DBUS-Server:HelloDBUSServerThisIsClient1"
**signal** time=1507725082.557260 sender=org.freedesktop.DBus -> destination=:1.34 serial=11 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameLost
string ":1.34"
**signal** time=1507725082.558629 sender=org.freedesktop.DBus -> destination=(null destination) serial=5 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged
string ":1.34"
string ":1.34"
string ""
另一个例子:
来自我的监视器的消息:
dbus.lowlevel.**Signal**Message path: /org/freedesktop/DBus, iface: org.freedesktop.DBus, member: NameAcquired, dest: :1.33
dbus.lowlevel.**MethodCall**Message path: /org/freedesktop/DBus, iface: org.freedesktop.DBus, member: AddMatch dest: org.freedesktop.DBus
dbus.lowlevel.**Signal**Message path: /org/freedesktop/DBus, iface: org.freedesktop.DBus, member: NameOwnerChanged, dest: (broadcast)
dbus.lowlevel.**MethodCall**Message path: /org/freedesktop/DBus, iface: org.freedesktop.DBus, member: Hello dest: org.freedesktop.DBus
来自dbus-monitor的消息:
**signal** time=1507725076.981426 sender=org.freedesktop.DBus -> destination=:1.33 serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired
string ":1.33"
**method call** time=1507725076.982076 sender=:1.33 -> destination=org.freedesktop.DBus serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
string "eavesdrop='true'"
**method return** time=1507725076.982138 sender=org.freedesktop.DBus -> destination=:1.33 serial=3 reply_serial=2
**method call** time=1507725081.489070 sender=:1.34 -> destination=org.freedesktop.DBus serial=1 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=Hello
**method return** time=1507725081.489177 sender=org.freedesktop.DBus -> destination=:1.34 serial=1 reply_serial=1
string ":1.34"
答案 0 :(得分:0)
监控总线的推荐方法是使用org.freedesktop.DBus.Monitoring.BecomeMonitor()
方法,而不是试图窃听每条消息(这会使您的代码变得脆弱,取决于窃听的总线配置规则)。
请参阅D-Bus specification on eavesdropping:
窃听与具有非平凡访问控制限制的总线交互不良,并且已被弃用。 BecomeMonitor方法(参见the section called “org.freedesktop.DBus.Monitoring.BecomeMonitor”)提供了一种监控总线的更好方法。
这可能会导致匹配过滤器无法看到某些消息。如果这不是问题,那么你的主循环可能有问题,虽然我无法快速查看它。
总的来说,当dbus-monitor
已经存在(并且显然有效)时,我不得不问你为什么要重新实现一个总线监视器?