2009-06-23 107 views
26

我正在嘗試轉儲所有活動線程的列表,包括每個線程的當前堆棧。我可以使用threading.enumerate()獲取所有線程的列表,但我無法找到從那裏進入堆棧的方法。所有活動線程的轉儲堆棧跟蹤

背景:一個Zope/Plone應用程序不時發作,消耗100%的cpu,需要重新啓動。我有一種感覺,它是一個不能正常終止的循環,但我無法在測試環境中重現它進行驗證。我設法註冊了一個可以從外部觸發的信號處理程序,所以我可以在情況再次發生時立即觸發一些代碼。如果我可以轉儲堆棧跟蹤所有活動的線程,那會給我一個線索出錯的地方。孔事情上是Python 2.4運行......

如何追查下來像這些情況的任何想法讚賞:)

乾杯, CHRISS

回答

8

使用Zope的,要安裝Products.signalstackmr.freeze;這些都是爲此目的而設計的!

向您的Zope服務器發送USR1信號,它會立即將所有線程的堆棧跟蹤轉儲到控制檯。即使所有Zope線程都被鎖定,它也會這樣做。

這些包間接使用threadframes;對於Python版本2.5及更高版本,當使用Zope的而不是時,可以使用sys._current_frames()函數構建相同的功能來訪問每線程堆棧幀。

Zope 2.12.5開始,此功能已集成到Zope本身中,無需再安裝其他軟件包。

+0

非常感謝,這正是我需要的! – Chriss 2009-06-24 14:33:33

0

有上ASPN適用的配方。你可以使用threading.enumerate()來獲得所有的tid,然後用一些合適的異常調用_async_raise()來強制堆棧跟蹤。

35

由於抖動指出在以前的答案sys._current_frames()給你你需要的V2.5 +。對於懶惰下面的代碼爲我工作可以幫助你:

print >> sys.stderr, "\n*** STACKTRACE - START ***\n" 
code = [] 
for threadId, stack in sys._current_frames().items(): 
    code.append("\n# ThreadID: %s" % threadId) 
    for filename, lineno, name, line in traceback.extract_stack(stack): 
     code.append('File: "%s", line %d, in %s' % (filename, 
                lineno, name)) 
     if line: 
      code.append(" %s" % (line.strip())) 

for line in code: 
    print >> sys.stderr, line 
print >> sys.stderr, "\n*** STACKTRACE - END ***\n" 
13

對於Python 3.3及更高版本,有faulthandler.dump_traceback()

下面的代碼產生類似的輸出,但包含線程名稱,並且可以增強以打印更多信息。

for th in threading.enumerate(): 
    print(th) 
    traceback.print_stack(sys._current_frames()[th.ident]) 
    print()