8. 将来
実は近い将来、シグナルをハンドルする仕組みが変わるようです。具体的にはシグナルをディスクリプタ経由で取得できるようになるらしいです。
私が知る範囲では、下記のインタフェースがLinuxカーネル2.6.22-rc1で用意されたようです。
long signalfd( int ufd, sigset_t * user_mask, size_t sizemask );
シグナルを通常の割り込み処理で補足するのではなく、ディスクリプタを経由してシグナルを受信するものなんだそうです。これによってディスクリプタに対してepoll(4)でPOLLINを待ったりselect(2)で待つことになります。しかし仕様上の不具合があったそうで、まだ混沌としている状況みたいです。
何かわかりましたら、また当レポートに上げようと思います。
9. 結論
シグナルとはプログラムに対する内外からの割り込みを処理できる機能です
- SIGSEGVなどのいわゆる異常終了時、何処の関数で落ちたのか解析したり、復帰できる。
- SIGTERMなどの外部からの終了要求時、作業中の資源を整理し、例えばDBと接続してる場合はコネクションを切断した後終了する等、いわゆるクリーンアップ処理ができる。
- シグナルで参照・編集される可能性のあるデータに対しハンドラ外からデータを参照・編集する場合、シグナル処理を待たせる事ができる。
旧シグナルとPOSIXシグナルについて
- 旧シグナルは環境依存な所がある。
- 旧シグナルができる事は、POSIXシグナルで全て実現できる。
- 汎用性・拡張性を考えて、POSIXシグナルで実装するべき。
シグナルハンドラ内で行ってよいのは下記のときです
- ハンドラ内の自動変数の操作。
- volatile修飾子の大域変数の操作。
- 「非同期シグナルセーフ」関数の呼び出し。
上記以外の処理を行った場合、下記のような問題が発生する可能性があります
- タイミングに依存する再現困難なデッドロックが発生する危険がある。
- コンパイラによって意図しない最適化が行われ、プログラムが誤動作する危険がある。
シグナルと相性がよくないものは次のとおりです
- pause(3)系関数、ただしerrno==EINTRを調べる事で対処可能。
- スレッド、なるべく共存は避ける。
シグナルハンドラを廃止し、スレッドとsigwait/sigwaitinfoのあわせ技によって上記の問題を解消できます
- スレッドを生成する前に補足対象のシグナルイベントをマスクする。
- シグナルイベントを処理する専用スレッドを生成する。
- そのスレッドがシグナルイベントを sigwait を使って見張る。
ただしその場合、スレッド独自の問題が発生します
- スレッドセーフ関数を使用。
- 同期対策を行う必要がある。
以上です。
参考文献
- 『詳解UNIXプログラミング』 W.リチャード スティーヴンス 著、大木 敦雄 訳、ピアソンエデュケーション、2000年12月
