背景としての雑談
EINTR
いわゆる割り込み可能なシステムコールによって返される可能性があるエラーです。システムコールの実行中にシグナルが発生した場合、そのシグナルは無視されません。信号ハンドラが定義されているが存在しない場合SA_RESTART
設定され、このハンドラが信号を処理すると、システムコールはEINTR
エラーコードを返します。
ちなみに、Pythonで使用すると、このエラーが頻繁に発生しますncurses
。
質問
POSIX規格で指定されているこの動作の背後にはどのような理由がありますか? (カーネル設計によって)回復されない可能性があることを理解できますが、カーネルレベルで自動的に再起動しないのはなぜですか?これは従来の理由ですか、それとも技術的な理由ですか?これが技術的な理由であれば、その理由は今でもまだ有効ですか?これが遺産上の理由なら、その歴史はどうなりますか?
ベストアンサー1
プログラムの残りの部分は不明な状態にあるため、信号ハンドラで重要な作業を実行するのは困難です。ほとんどのシグナルハンドラは、後でプログラムの他の場所で確認して処理するフラグを設定します。
システムコールが自動的に再開されない理由:
ソケットからデータを受け取るアプリケーションを想像してください。ブロックして中断できない recv()
システムコール。私たちのシナリオでは、データ転送は非常に遅く、プログラムは長い間このシステムコールに常駐しています。プログラムにはSIGINT
、フラグ(他の場所で評価)を設定し、SA_RESTART
自動的に再起動するようにシステムコールを設定するシグナルハンドラがあります。プログラムがrecv()
データを待っていると想像してください。しかし、データは到着しません。システムコールのブロック。これでプログラムはユーザーからキャプチャしますctrl。cシステムコールが中断され、フラグを設定したシグナルハンドラが実行されます。その後、recv()
再起動し、まだデータを待っています。recv()
フラグを評価し、プログラムを正常に終了する機会なしにイベントループが中断されます。
設定されていない場合SA_RESTART
:
上記のシナリオでSA_RESTART
設定しないと、再起動するのではなくrecv()
受信されます。EINTR
続行できるように、システムコールが終了します。もちろん、プログラムは(できるだけ早く)フラグ(信号ハンドラによって設定されている)を確認して整理する必要があります。