Dbus/GLib 主循环、后台线程
我一般从 DBus 和事件驱动编程开始。我试图创建的服务实际上由三个部分组成,但其中两个部分实际上是“服务器”。
1) 实际的 DBus 服务器通过 HTTPS 与远程网站通信、管理会话并向客户端传送信息。
2) 服务的另一部分每 2 分钟调用一次保持活动页面,以使会话在外部网站上保持活动状态
3) 客户端调用服务以从服务检索信息。
我找到了一些简单的示例程序。我正在尝试使它们适应原型#1 和#2。而不是为两者构建单独的程序。我认为我可以在一个单线程进程中运行它们。
我看到的问题是我在保持活动线程中调用 time.sleep(X) 。线程进入睡眠状态,但永远不会醒来。我认为 GIL 不是由 GLib 主循环释放的。
这是我的线程代码:
class Keepalive(threading.Thread):
def __init__(self, interval=60):
super(Keepalive, self).__init__()
self.interval = interval
bus = dbus.SessionBus()
self.remote = bus.get_object("com.example.SampleService", "/SomeObject")
def run(self):
while True:
print('sleep %i' % self.interval)
time.sleep(self.interval)
print('sleep done')
reply_status = self.remote.keepalive()
if reply_status:
print('Keepalive: Success')
else:
print('Keepalive: Failure')
从打印语句中,我知道睡眠开始,但我从未看到“睡眠完成”。
这是主要代码:
if __name__ == '__main__':
try:
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
session_bus = dbus.SessionBus()
name = dbus.service.BusName("com.example.SampleService", session_bus)
object = SomeObject(session_bus, '/SomeObject')
mainloop = gobject.MainLoop()
ka = Keepalive(15)
ka.start()
print('Begin main loop')
mainloop.run()
except Exception as e:
print(e)
finally:
ka.join()
一些其他观察结果:
我看到“开始主循环”消息,所以我知道它正在获得控制。然后,我看到“sleep %i”,之后就什么也没有了。
如果我^C,那么我会看到“睡眠完成”。大约 20 秒后,我从 self.run() 收到异常,远程应用程序没有响应:
DBusException:org.freedesktop.DBus.Error.NoReply:未收到回复。可能的原因包括:远程应用程序未发送回复、消息总线安全策略阻止回复、回复超时或网络连接中断。
在服务器中运行保持活动代码的最佳方式是什么?
谢谢,
I'm starting out with DBus and event driven programming in general. The service that I'm trying to create really consists of three parts but two are really "server" things.
1) The actual DBus server talks to a remote website over HTTPS, manages sessions, and conveys info the clients.
2) The other part of the service calls a keep alive page every 2 minutes to keep the session active on the external website
3) The clients make calls to the service to retrieve info from the service.
I found some simple example programs. I'm trying to adapt them to prototype #1 and #2. Rather than building separate programs for both. I thought I that I can run them in a single, two threaded process.
The problem that I'm seeing is that I call time.sleep(X) in my keep alive thread. The thread goes to sleep, but won't ever wake up. I think that the GIL isn't released by the GLib main loop.
Here's my thread code:
class Keepalive(threading.Thread):
def __init__(self, interval=60):
super(Keepalive, self).__init__()
self.interval = interval
bus = dbus.SessionBus()
self.remote = bus.get_object("com.example.SampleService", "/SomeObject")
def run(self):
while True:
print('sleep %i' % self.interval)
time.sleep(self.interval)
print('sleep done')
reply_status = self.remote.keepalive()
if reply_status:
print('Keepalive: Success')
else:
print('Keepalive: Failure')
From the print statements, I know that the sleep starts, but I never see "sleep done."
Here is the main code:
if __name__ == '__main__':
try:
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
session_bus = dbus.SessionBus()
name = dbus.service.BusName("com.example.SampleService", session_bus)
object = SomeObject(session_bus, '/SomeObject')
mainloop = gobject.MainLoop()
ka = Keepalive(15)
ka.start()
print('Begin main loop')
mainloop.run()
except Exception as e:
print(e)
finally:
ka.join()
Some other observations:
I see the "begin main loop" message, so I know it's getting control. Then, I see "sleep %i," and after that, nothing.
If I ^C, then I see "sleep done." After ~20 seconds, I get an exception from self.run() that the remote application didn't respond:
DBusException: org.freedesktop.DBus.Error.NoReply: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.
What's the best way to run my keep alive code within the server?
Thanks,
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
使用
gobject
时,您必须通过调用gobject.threads_init()
显式启用多线程。有关背景信息,请参阅 PyGTK 常见问题解答。除此之外,出于您所描述的目的,超时似乎更合适。使用方式如下:
这会每隔
time_in_ms
(毫秒)秒调用keepalive
函数。更多详细信息,请再次参阅 PyGTK 参考。You have to explicitly enable multithreading when using
gobject
by callinggobject.threads_init()
. See the PyGTK FAQ for background info.Next to that, for the purpose you're describing, timeouts seem to be a better fit. Use as follows:
This calls the
keepalive
function everytime_in_ms
(milli)seconds. Further details, again, can be found at the PyGTK reference.