2013-04-19 41 views
1

我正在用Python線程(包括守護進程)做一些粗糙的事情。Python守護進程中關閉問題的調試技巧

我在有些測試中得到一個間歇性的錯誤:

Exception in thread myconsumerthread (most likely raised during interpreter shutdown): 

注意,有沒有提供堆棧跟蹤/異常的詳細信息。

仔細檢查我自己的代碼沒有幫助,但是我對調試的下一步感到有點不知所措。 我可以使用哪些調試技術來了解關於哪些異常可能會導致關閉期間運行時關閉的更多信息?

小字:

  • 的Windows,CPython的,2.7.2 - 在Ubuntu不reproduceable。
  • 問題發生時間約3% - 如此可重現,只是不可靠。
  • myconsumerthread中的代碼有一個catch-all異常處理程序,它嘗試將異常的名稱寫入sys.stderr。 (可能sys已被關閉?)
  • 嫌疑人該問題與關閉守護進程線程有關很快;在他們完全初始化之前。有些東西在this區域,但我沒有什麼證據 - 當然不足以指向Python錯誤。
  • 哈,我發現了一個新的症狀,標誌着我陷入瘋狂的轉折點!
    • 如果我import time測試工具(不活碼),並從來沒有使用它,頻率下降至約0.5%。
    • 如果我在我的測試工具中發現我import turtle(我發誓我的生活中,我的代碼中沒有烏龜圖形;我選擇這個作爲我可以快速找到的最不相關的庫)異常開始被捕獲到另一個線程中,它發生在約運行的
+0

哦:這可能是有關個人興趣(http://stackoverflow.com/questions/8456395/threaded-importing-while-interpreter-shuts-down) – Oddthinking

+0

劃痕,去年的想法。我的導入在線程啓動之前完成。 – Oddthinking

+2

可能相關:http://bugs.python.org/issue4106 https://github.com/paramiko/paramiko/issues/17 http://stackoverflow.com/questions/1745232/solving-thread-cleanup-on- paramiko – Patashu

回答

1

我也遇到過,有幾次同樣的錯誤。我試圖找到/生成顯示確切消息的示例。

在此之前,如果我的記憶能爲我服務,那麼這些就是我關注的領域。

  • 尋找端口,文件,隊列等...在守護進程線程之外被移除或關閉。
  • 檢查守護進程線程中的阻塞調用。 IE瀏覽器Queue.get(block=True)pyserial.read() - 與超時=無

挖多一點我看到相同類型的錯誤彈出有關隊列的see comments here後。

我覺得很奇怪,它沒有顯示回溯。您可以嘗試將註釋全部註釋掉,並讓Python將其發送到std.error。希望你能看到你身上的死亡。

更新
我知道我已經看到這個問題之前......下面,你會發現,產生錯誤(其中許多人實際上)的例子。請注意,沒有其他追溯消息...爲了完整起見,在看到錯誤消息後,取消註釋queue.get行並註釋掉time.sleep。錯誤應該消失。 再次重新運行此操作後,錯誤不會顯示出來......這與您在零星故障率中看到的內容一致...您可能需要運行幾次以查看錯誤。

我通常使用time.sleep(x)如果阻塞IO如get()read()不提供超時方法OR沒有被使用(用戶界面刷新例如)阻塞調用節流線程。

這就是說,我相信有一個線程在等待time.sleep()調用時被關閉的問題。我相信這個電話是我每次都得到的,但我不知道sleep方法中究竟是什麼導致了這個問題。據我所知,還有其他阻塞調用顯示相同的行爲。

import time 
import Queue 
from threading import Thread 

SLAVE_CNT = 50 
OWNER_CNT = 10 
MASTER_CNT = 2 

class ThreadHungry(object): 
    def __init__(self): 
     self.rx_queue = Queue.Queue() 

    def start(self): 
     print "Adding Masters..." 
     for x in range(MASTER_CNT): 
      self.owners = [] 
      print "Starting slave owners..." 
      for y in range(OWNER_CNT): 
       owner = Thread(target=self.__owner_action) 
       owner.daemon = True 
       owner.start() 
       self.owners.append(owner) 

    def __owner_action(self): 
     self.slaves = [] 
     print "\tStarting slaves..." 
     for x in range(SLAVE_CNT): 
      slave = Thread(target=self.__slave_action) 
      slave.daemon = True 
      slave.start() 
      self.slaves.append(slave) 

     while(1): 
      time.sleep(1) 
      #self.rx_queue.get(block=True) 

    def __slave_action(self): 
     while(1): 
      time.sleep(1) 
      #self.rx_queue.get(block=True) 


if __name__ == "__main__": 
    c = ThreadHungry() 
    c.start() 

    # Stop the threads abruptly after 5 seconds 
    time.sleep(5) 
+0

我試圖跟進您的建議。註釋了全部內容,並沒有改變,沒有使用端口。不使用文件(儘管stderr可能會計數)。我的代碼中間有一個Queue,所以這可能會有所幫助。 – Oddthinking

+0

@Oddthinking你可能會考慮在你的異常處理程序中使用Python調試器('import pdb; pdb.set_trace()')來查找。我有我的懷疑它會工作,因爲它正在關閉事件中死去。仍然可能值得一試。 –

+0

在調試器中手動運行100次。沒有看到問題。感到無聊,繼續前進。 – Oddthinking