2014-11-02 38 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()