すべてのアクティブなスレッドのスタックトレースをダンプします
-
06-07-2019 - |
質問
それぞれの現在のスタックを含むすべてのアクティブなスレッドのリストをダンプしようとしています。 threading.enumerate()を使用してすべてのスレッドのリストを取得できますが、そこからスタックに到達する方法がわかりません。
背景:Zope / Ploneアプリは時々フリークし、CPUの100%を消費し、再起動する必要があります。私はそれが適切に終了しないループだと感じていますが、検証のためにテスト環境でそれを再現することはできません。外部からトリガーできるシグナルハンドラーを登録したので、状況が再び発生するとすぐにコードをトリガーできます。すべてのアクティブなスレッドのスタックトレースをダンプできれば、何が悪いのかを知る手がかりになるでしょう。穴はPython 2.4で実行されます...
このような状況を追跡する方法についてのアイデアはありがたいです:)
乾杯、 クリス
解決
Zopeを使用する場合、 Products.signalstack
<をインストールします。 / a>または mr.freeze ;これらはまさにこの目的のために設計されました!
ZopeサーバーにUSR1シグナルを送信すると、すぐにすべてのスレッドのスタックトレースがコンソールにダンプされます。すべてのZopeスレッドがロックされていても、これを行います。
これらのパッケージは内部的に間接的に threadframes
; Pythonバージョン2.5以降では、Zopeを使用していない 場合、 sys._current_frames()
スレッドごとのスタックフレームにアクセスする関数。
Zope 2.12.5 現在、この機能はZope自体に統合されています。追加のパッケージをインストールする必要はもうありません。
他のヒント
以前の回答でジッタが指摘しているように、 sys._current_frames()
はv2.5 +に必要なものを提供します。怠zyな人のために、次のコードスニペットが私のために働いて、あなたを助けるかもしれません:
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"
Python 3.3以降には、 faulthandlerがあります。 .dump_traceback()
。
以下のコードは同様の出力を生成しますが、スレッド名が含まれ、より多くの情報を印刷するように拡張できます。
for th in threading.enumerate():
print(th)
traceback.print_stack(sys._current_frames()[th.ident])
print()
2.4。残念な。 Python 2.5以降には sys._current_frames()
があります。
しかし、 threadframe を試すことができます。また、メイクファイルで問題が発生した場合は、 setup.pyを試すことができます。スレッドフレーム用
完全を期すために、 Products.LongRequestLogger はボトルネックを特定するのに非常に役立ちます。そのためには、特定の間隔でスタックトレースをダンプします。
ASPN に該当するレシピがあります。 threading.enumerate()
を使用してすべてのtidを取得し、適切な例外を指定して_async_raise()を呼び出すだけで、スタックトレースを強制できます。