【问题标题】:Repeatedly starting Gtk application using multiprocessing.Process (or: how to sandbox Gtk in python)使用 multiprocessing.Process 反复启动 Gtk 应用程序(或:如何在 python 中对 Gtk 进行沙箱处理)
【发布时间】:2013-09-18 23:01:52
【问题描述】:

简介

: 我需要(内存)在 python 中对 Gtk/Gstreamer 应用程序进行沙箱处理并定期重新启动它。

: 我在一个库 (gstreamer) 中遇到内存泄漏,我将其用于从相机中获取数据的更大代码块。只是为了避免关于这个问题的争论,我试图解决这个问题已经有一段时间了,但无法解决。我需要相机数据,所以我决定尝试破解一个解决方案,这应该是手动破解的自动化,即定期执行并在内存填满之前重新启动软件。

但是,我一点也不习惯 Gtk,而且我对 python 的内存管理知之甚少。因此,我遇到了问题。

设置

所以现在,程序是使用 Gtk3 用 python 编写的。我有一个 myPythonObjectWithGtkStuff ,它本质上是一个更花哨的版本 http://bazaar.launchpad.net/~jderose/+junk/gst-examples/view/head:/webcam-1.0 。但特别是__init__()run() 中的Gtk 部分是相同的。 (请注意这一行 http://bazaar.launchpad.net/~jderose/+junk/gst-examples/view/head:/webcam-1.0#L51 以及 on_sync_message() 函数,这可能是一个红鲱鱼,但它们处理使用 xid 句柄将 gstreamer 流定向到 Gtk 绘图区域)

问题/解决方案 1

我想象它的工作方式是在一个 while 循环中创建包含所有代码的整个对象。然后在 Gtk 主循环中的某个时间点调用window.destroy()。它将返回到 while 循环并创建另一个对象,等等。

# shitty hack to restart the Gtk application once it got destroyed
while(1):
    startVC(args)

def startVC(args):    
    mainloop = GObject.MainLoop()
    obj = myPythonObjectWithGtkStuff(args)
    obj.run()
    del obj

到目前为止一切顺利。如果我按照上面所写的方式进行操作,一切正常。这个解决方案的问题是它没有释放obj 的内存。 (我认为主要是内存泄漏的东西仍然存在,我不确定)。

编辑:

在我调用 window.destroy() 的那一刻,Gtk 窗口关闭,我可以看到内存使用量下降到某个稳定的基值。一旦 Gtk 再次启动,内存使用量将返回到之前的操作内存使用量加上一些与内存泄漏产生的量相对应的额外内存。

问题/解决方案 2

现在我想我可以在一个进程中启动 Gtk,然后在它返回时终止它并启动一个新进程。

while(1):
    p = Process(target=startVC, args=(args,))            
    p.start()
    p.join()        
    p.terminate()

这里的问题是它第一次启动非常好,但是一旦第一个进程返回并且循环启动第二个进程,我在__init()__()myPythonObjectWithGtkStuff 中调用self.window = Gtk.Window() 时收到以下错误:

Gdk-WARNING **: captureVideo.py: Fatal IO error 11 (Resource temporarily unavailable) on X server :0.

有一点交替
Gdk-WARNING **: captureVideo.py: Fatal IO error 0 (Success) on X server :0.

怎么办?

我现在需要的是解决这两个问题中的任何一个。对于第一个解决方案,我如何确保该对象从内存中完全删除,或者如何避免解决方案 2 的 X 服务器错误。

可能是调用我的obj 中的self.window.destroy() 不足以杀死所有Gtk 东西。这是关闭 Gtk 应用程序的正确方法吗?

【问题讨论】:

    标签: python memory-leaks gtk sandbox xserver


    【解决方案1】:

    我现在完成了类似这个单独的小脚本

    # file: keepAliveWrapper.py
    
    import sys
    import subprocess as sp
    
    if __name__ == "__main__":
        args = sys.argv[1:]
        while(1):                
            print("calling: python {args}".format(args=' '.join(args)))
    
            p = sp.Popen("python {args}".format(args=' '.join(args)),
                         shell=True, stdout=sp.PIPE, stderr=sp.STDOUT)
            output =  p.communicate()[0]
    

    它将它管理的脚本及其命令行参数作为参数。所以基本上不是在命令行中调用python gtkProgram.py -d /home/peter/test -e 10,而是现在运行python keepAliveWrapper.py gtkProgram.py -d /home/peter/test -e 10

    如果有人有更聪明的想法,请告诉我。

    P.S.:供将来参考:p.communicate() 允许解析保持活动的程序的输出。即这样可以传递“信号”来决定是否中断while循环。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-17
      相关资源
      最近更新 更多