web-dev-qa-db-ja.com

すべてのアクティブなスレッドのスタックトレースをダンプします

それぞれの現在のスタックを含むすべてのアクティブなスレッドのリストをダンプしようとしています。 threading.enumerate()を使用してすべてのスレッドのリストを取得できますが、そこからスタックにアクセスする方法がわかりません。

背景:Zope/Ploneアプリはときどき異常になり、CPUを100%消費するため、再起動する必要があります。正しく終了しないループだと感じますが、検証用のテスト環境では再現できません。外部からトリガーできるシグナルハンドラーを登録できたので、状況が再発するとすぐにコードをトリガーできます。すべてのアクティブなスレッドのスタックトレースをダンプできれば、何がうまくいかないのかがわかります。穴のことはpython 2.4 .. ..

このような状況を追跡する方法についてのアイデアはありがたいです:)

乾杯、クリス

28
Chriss

Zopeを使用する場合は、 _Products.signalstack_ または mr.freeze ;をインストールします。これらはまさにこの目的のために設計されました!

USR1信号をZopeサーバーに送信すると、すべてのスレッドのスタックトレースがすぐにコンソールにダンプされます。すべてのZopeスレッドがロックされている場合でも、これを実行します。

内部的には、これらのパッケージは間接的に threadframes ;を使用します。 Pythonバージョン2.5以降の場合、notがZopeを使用している場合、 sys._current_frames() スレッドごとのスタックフレームにアクセスする関数。

Zope 2.12.5 以降、この機能はZope自体に統合されており、追加のパッケージをインストールする必要はありません。

10
Martijn Pieters

以前の回答でジッターが指摘しているように、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"
39
codeasone

Python 3.3以降の場合、 faulthandler.dump_traceback() があります。

以下のコードは同様の出力を生成しますが、スレッド名が含まれており、より多くの情報を出力するように拡張できます。

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

2.4。残念な。 Python 2.5からsys._current_frames()があります。

しかし、 threadframe を試すことができます。そして、makefileで問題が発生した場合は、これを試すことができます setup.py for threadframe

スレッドフレーム使用時の出力例

7
jitter

完全を期すために、 Products.LongRequestLogger はボトルネックを特定するのに非常に役立ち、そうすることで特定の間隔でスタックトレースをダンプします。

1
gforcada

[〜#〜] aspn [〜#〜] に適用可能なレシピがあります。 threading.enumerate()を使用してすべてのtidを取得してから、適切な例外を除いて_async_raise()を呼び出すだけで、スタックトレースを強制できます。

0
jwoolard