2014-11-02 81 views
0

我注意到在我通过python使用gstreamer(使用Ubuntu 14.04的python-gst-1.0 deb软件包版本1.2.0-1)之后,我似乎每个编码器运行都有一个杂散线程。我在我写的模块中有gstreamer接口,它在模块中执行gobject.mainloop,并且执行mainloop.quit(),所以我不希望它是主循环本身。Python gstreamer中的杂散线程使用

几运行后,threading.enumerate()是表示:

[<_MainThread(MainThread, started 140079923849024)>, 
<_DummyThread(Dummy-1, started daemon 140079768815360)>, 
<_DummyThread(Dummy-3, started daemon 140079785338624)>, 
<_DummyThread(Dummy-4, started daemon 140079418832640)>, 
<_DummyThread(Dummy-2, started daemon 140079802386176)>] 

值得庆幸的是,他们开始与守护程序,所以程序将退出,但我在一个不知如何清洗这些了。它们正在影响使用Ctrl-C退出脚本的可能性,因为KeyboardInterrupt并不总是看起来像MainThread。我结束我的运行循环使用:

try: 
    time.sleep(899.0) 
except KeyboardInterrupt: 
    pass 

time.sleep(1.0) 

这应该让我按Ctrl-C快速两倍于第一时间捕获的try /除了中止循环超时,而第二个对1S没有处理程序睡觉,从而退出。但是,对于流水线程,第二个Ctrl-C在某个层次上从未见过,所以我需要按Ctrl-Z才能到达shell并强制终止脚本。我不喜欢它。

任何人都知道这个流浪线程是什么,以及如何让它与我合作并为我而死?我即将在正在运行的进程中断开gdb以确定它可能是什么。

的类代码(剥离下来以去除不相关部分):

class GstEncoder: 
    def __init__(self, metadata, mediainfo): 
     self.error = None 

     # used for controlling logic which I removed for clarity 
     self.metadata = metadata 
     self.mediainfo = mediainfo 

     # Create a pipeline in self.pipeline 
     self.setupPipeline() 

     # Put in the MainLoop 
     self.mainloop = GObject.MainLoop() 
     self.context = self.mainloop.get_context() 
     self.abort = False 

    def __del__(self): 
     logger.info("Dying gasp!") 
     if self.mainloop.is_running(): 
      self.mainloop.quit() 
     self.pipeline.unref() 

    def start(self): 
     # Set in playing mode 
     self.pipeline.set_state(Gst.State.PLAYING) 

     # actually only used in some situations, removed the controlling logic for clarity 
     GObject.timeout_add_seconds(900, self.timedOut) 
     GObject.timeout_add_seconds(30, self.progressReport) 

     try: 
      self.abort = False 
      self.mainloop.run() 
     except KeyboardInterrupt: 
      logger.warning("Aborted by Ctrl-C") 
      self.abort = True 
      self.mainloop.quit() 
      raise KeyboardInterrupt 

     # Stop the pipeline 
     self.pipeline.set_state(Gst.State.NULL) 
     return self.error 

    def progressReport(self): 
     position = self.pipeline.query_position(Gst.Format.TIME)[1] 
     duration = self.pipeline.query_duration(Gst.Format.TIME)[1] 
     if self.abort: 
      return False 
     percentage = 0.0 if duration == 0 \ 
         else float(position)/float(duration) * 100.0 
     logger.info("Progress: %s/%s (%.2f%%)" % (Gst.TIME_ARGS(position), 
       Gst.TIME_ARGS(duration), percentage)) 
     return True 

    def timedOut(self): 
     if self.abort: 
      return False 
     self.error = "Aborted by watchdog timer" 
     logger.warning(self.error) 
     self.abort = True 
     self.mainloop.quit() 
     return False 

这被例示为:https://s3.amazonaws.com/beirdo-share/before.png

+0

我将需要一些示例代码来回答,我一直在Python中使用gstreamer很多,从未遇到过这个问题。 (例如,对于每个编码器运行,你的意思是什么?) – 2014-11-02 15:12:57

+0

每次运行时,我的意思是每次我实例化一个在其中执行gstreamer的类。我会很快用一些示例代码更新这个问题。在你的mainloop完成并退出之后,你是否尝试过使用“threading.enumerate()”,并且你没有重新输入管道? – Beirdo 2014-11-02 20:53:50

+0

如果没有实际的工作代码,很难重现:)我相信这是其他代码/设置的问题。例如,下面是代码的精简版,它不会出现任何问题:http://www.fpaste.org/147332/14979029/ – 2014-11-03 01:45:55

回答

1

I”:

err = None 
# Filename, etc is in metadata 
encoder = GstEncoder(metadata, mediainfo) 
if encoder.error: 
    err = encoder.error 
if not err: 
    err = encoder.start() 

if err: 
    logger.error(err) 

encoder = None 
print threading.enumerate() 

一个例子管道可以在可见我遇到了一个听起来相同的问题:Ctrl-C触发KeyboardInterrupt,但由于非守护进程gstreamer线程,进程不会退出。解决方法是在应用程序启动时调用GObject.threads_init()