HN 日本語サマリー

← 一覧へ戻る
プログラミング

Pythonのシグナルハンドラ内でprintを呼び出すのは安全か?

Is it safe to call print in a Python signal handler? (iafisher.com)

13 pointsby hellerve1 コメント

要約

Pythonのシグナルハンドラ内でprint関数を呼び出すことの安全性について、極端な状況下でのテスト結果が示されています。通常、シグナルハンドラ内でのI/O操作は推奨されませんが、CPythonの実装ではユーザー定義のシグナルハンドラが低レベルのCシグナルハンドラから分離されているため、C言語のような厳しい制約はありません。しかし、シグナルハンドラが再入可能である場合、極端な信号の連続受信によりprint呼び出しがクラッシュする可能性があることが実験で示されました。

全文翻訳

Pythonのシグナルハンドラ内でprintを呼び出すのは安全か? シリーズ:Pythonにおけるシグナルハンドリング Pythonには2つのシグナルハンドラがある シグナルをブロックすることは、無視することとは異なる PythonはSA_RESTARTを渡さない 安全なシグナルイディオム Pythonのシグナルハンドラは予期せず再入可能である Pythonのシグナルハンドラ内でprintを呼び出すのは安全か? time.sleepとシグナル割り込み Pythonのsiginterruptは紛らわしい 以前に、Pythonには2つのシグナルハンドラがあるため、シグナルハンドラが呼び出し可能な関数に対する厳格な制限はPythonには適用されないことを学びました。なぜなら、CPythonは、それらの制限が適用される低レベルのCシグナルハンドラ内でユーザー提供のPythonシグナルハンドラを呼び出すのではなく、インタプリタが一貫した状態になったときに後で呼び出されるように手配するからです。また、Pythonのシグナルハンドラは予期せず再入可能であることも学びました。つまり、Pythonシグナルハンドラが実行中にシグナルが到着した場合、最初の呼び出しの途中でシグナルハンドラが再度呼び出される可能性があります。printの呼び出しの途中でシグナルハンドラが再入された場合、どうなるでしょうか? 自分自身に急速な信号の連射を送ることで、それをストレステストしてみましょう。 import os, signal, subprocess def sighandler(_signo, _frame): print("signal received") signal.signal(signal.SIGUSR1, sighandler) subprocess.run("for x in {1..50}; do kill -USR1 %s; done" % os.getpid(), shell=True) このプログラムを私のマシンで実行したところ、以下のようになりました。 File "multiple_signals.py", line 6, in sighandler print("signal received") File "multiple_signals.py", line 6, in sighandler print("signal received") File "multiple_signals.py", line 6, in sighandler print("signal received") [Previous line repeated 2 more times] RuntimeError: reentrant call inside <_io.BufferedWriter name='<stdout>'> このテストプログラムは、極端な状況下では、シグナルハンドラ内でprintを呼び出すとプログラムがクラッシュする可能性があることを示しています。この状況は極端な状況を必要とすることを強調したいと思います。実際のプログラムがこれらの条件に直面する可能性は低いですが、それでも例外で失敗することは、C言語における安全でないシグナルハンドラの潜在的な結果(デッドロック、データ構造の破損、サイレントフェイルなど)よりも許容できます。したがって、私はこれをシグナルに関する別のトリビアとして扱い、シグナルハンドラを書く上での実用的な考慮事項ではないと考えていますが、それでもシグナルハンドラで些細でない作業を行うことは避けるべきだとアドバイスします。