faulthandler --- Python tracebackのダンプ

バージョン 3.3 で追加.


このモジュールは、例外発生時、タイムアウト時、ユーザシグナルの発生時などのタイミングでpython tracebackを明示的にダンプするための関数を含んでいます。これらのシグナル、SIGSEGVSIGFPESIGABRTSIGBUSSIGILL に対するフォールトハンドラをインストールするには faulthandler.enable() を実行してください。python起動時に有効にするには環境変数 PYTHONFAULTHANDLER を設定するか、コマンドライン引数に -X faulthandler を指定してください。

Pythonのフォールトハンドラは、apportやWindowsのフォールトハンドラのようなシステムフォールトハンドラと互換性があります。このモジュールは sigaltstack() 関数が使用可能であればシグナルハンドラ用に代替スタックを利用します。これによってスタックオーバーフロー時にもスタックトレースを出力することができます。

フォールトハンドラは絶望的なケースで呼び出されます。そのためシグナルセーフな関数しか使うことができません (例: ヒープメモリ上にメモリ確保はできません)。この制限により、tracebackのダンプ機能は通常のPythonのtracebackと比べてごく僅かなものです:

  • ASCIIのみサポートされます。エンコード時には backslashreplace エラーハンドラを使用します。

  • すべての文字列は500文字以内に制限されています。

  • ファイル名、関数名、行数のみ表示します。(ソースコードの表示はありません)

  • 100フレーム、100スレッドに制限されています。

  • 順番は保持されます: 最新の呼び出しが最初に表示されます。

デフォルトでは、Pythonのtracebackは sys.stderr に書き出されます。tracebackを見るには、対象アプリケーションはターミナル上で実行しなければなりません。 faulthandler.enable() に渡す引数によってログファイルを指定することができます。

モジュールはC言語で実装されているので、アプリのクラッシュ時でもPythonがデッドロックした場合でもダンプができます。

The Python Development Mode calls faulthandler.enable() at Python startup.

参考

Module pdb

Interactive source code debugger for Python programs.

Module traceback

Standard interface to extract, format and print stack traces of Python programs.

tracebackのダンプ

faulthandler.dump_traceback(file=sys.stderr, all_threads=True)

全スレッドのtracebackを file へダンプします。もし all_threadsFalse であれば、現在のスレッドのみダンプします。

参考

traceback.print_tb(), which can be used to print a traceback object.

バージョン 3.5 で変更: Added support for passing file descriptor to this function.

フォールトハンドラの状態

faulthandler.enable(file=sys.stderr, all_threads=True)

フォールトハンドラを有効にします。 SIGSEGVSIGFPESIGABRTSIGBUSSIGILL シグナルに対して Pythonのtracebackをダンプするハンドラをインストールします。もし all_threadsTrue であれば、すべての実行中のスレッドについてtracebackをダンプします。そうでなければ現在のスレッドのみダンプします。

The file must be kept open until the fault handler is disabled: see issue with file descriptors.

バージョン 3.5 で変更: Added support for passing file descriptor to this function.

バージョン 3.6 で変更: On Windows, a handler for Windows exception is also installed.

バージョン 3.10 で変更: The dump now mentions if a garbage collector collection is running if all_threads is true.

faulthandler.disable()

フォールトハンドラを無効にします: enable() によってインストールされたシグナルハンドラをアンインストールします。

faulthandler.is_enabled()

フォールトハンドラが有効かどうかチェックします。

タイムアウト後にtracebackをダンプする

faulthandler.dump_traceback_later(timeout, repeat=False, file=sys.stderr, exit=False)

timeout 秒経過後か、repeatTrue の場合は timeout 秒おきに全スレッドの traceback をダンプします。もし exitTrue であればtracebackをダンプした後、status=1で _exit() を呼び出します。(注: _exit() を呼び出すとプロセスを即座に終了します。つまりファイルバッファのクリアといった終了処理を行いません。)関数が2回呼ばれた場合、最新の呼び出しが前回の呼び出しパラメータを引き継いでタイムアウト時間をリセットします。タイマーの分解能は1秒未満です。

The file must be kept open until the traceback is dumped or cancel_dump_traceback_later() is called: see issue with file descriptors.

This function is implemented using a watchdog thread.

バージョン 3.7 で変更: This function is now always available.

バージョン 3.5 で変更: Added support for passing file descriptor to this function.

faulthandler.cancel_dump_traceback_later()

dump_traceback_later() の最新の呼び出しをキャンセルします。

ユーザシグナルに対してtracebackをダンプする

faulthandler.register(signum, file=sys.stderr, all_threads=True, chain=False)

ユーザシグナルを登録します: すべてのスレッドでtracebackをダンプするために signum シグナルをインストールします。ただし all_threadsFalse であれば現在のスレッドのみ file にダンプします。もし chain が True であれば以前のハンドラも呼び出します。

The file must be kept open until the signal is unregistered by unregister(): see issue with file descriptors.

Windowsでは利用不可です。

バージョン 3.5 で変更: Added support for passing file descriptor to this function.

faulthandler.unregister(signum)

ユーザシグナルを登録解除します: register() でインストールした signum シグナルハンドラをアンインストールします。シグナルが登録された場合は True を返し、そうでなければ False を返します。

Windowsでは利用不可です。

ファイル記述子の問題

enable()dump_traceback_later() ならびに register() は引数 file に渡されたファイル記述子を保持します。ファイルが閉じられファイル記述子が新しいファイルで再利用された場合や、os.dup2() の使用でファイル記述子が置き換えた場合、 traceback の結果は別のファイルへ書き込まれます。ファイルが置き換えられた場合は、毎回これらの関数を呼び出しなおしてください。

使用例

Example of a segmentation fault on Linux with and without enabling the fault handler:

$ python3 -c "import ctypes; ctypes.string_at(0)"
Segmentation fault

$ python3 -q -X faulthandler
>>> import ctypes
>>> ctypes.string_at(0)
Fatal Python error: Segmentation fault

Current thread 0x00007fb899f39700 (most recent call first):
  File "/home/python/cpython/Lib/ctypes/__init__.py", line 486 in string_at
  File "<stdin>", line 1 in <module>
Segmentation fault