2

介绍

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

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

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

设置

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

问题/解决方案 1

我想象它的工作方式是在一个while循环中创建包含所有代码的整个对象。window.destroy()然后在 Gtk 主循环中的某个时间点调用 。它将返回到 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()

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

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 服务器错误。

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

4

1 回答 1

0

我现在最终做了类似这个单独的小脚本

# 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在你现在运行的命令行中调用 saypython keepAliveWrapper.py gtkProgram.py -d /home/peter/test -e 10

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

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

于 2013-09-19T13:37:39.207 回答