#navi_header|Perl| '' シグナルは非常に扱いが難しいです。ここにまとめた文章は依然として「メモ」扱いです。より正確で厳密な記述に、将来書き換えられる可能性もありますし、あるいはそうした外部リソースのリンクが追記される可能性があります。つまり・・・あの、その、これ、まだ私的なメモの段階なので、あんまり信用されるとちょっとまずいです。という感じです。 '' * 簡単なように見えて面倒くさいシグナル処理 Inter Process Communication (IPC) でのシグナル(signal)は、非常に奥が深い。というのも + マルチスレッドプログラミングにおいてどうなるのか? + シグナルハンドラの処理中に、同じシグナルを受信して同じシグナルハンドラに入ってしまう、いわゆる"再突入問題"( '' re-entrant problem '' )をどう処理するか? + シグナルハンドラ中で"re-entrant"でない((プロセス中で同時に呼ばれることを想定せず、プロセスコンテキスト中でグローバル変数を裏側で持ってしまっている、標準関数など))関数を呼ぶとどうなるか? などなど、"同時性"についてかなり面倒くさい考慮が必要になる機構だからだ。 Cから使えるAPIにしても、以下の二系統が存在する。 + 初期に作られた"signal(2)"システムコール + POSIXで制定された"sigaction(2)"系のシステムコール 一般に関数のI/Fが簡便であるのはsignal(2)の方である。シグナルをブロックしたり、ブロック対象のシグナルを細かく制御したりする場合、また子プロセスの終了を緻密に検出したい場合などは、sigaction(2)系を用いると良いらしい。 * シグナル関係のURL - perldoc -- IPCとしてのSignal : http://perldoc.perl.org/perlipc.html#Signals -- 遅延("Deferred")シグナルについて : http://perldoc.perl.org/perlipc.html#Deferred-Signals-(Safe-Signals) -- "sigtrap"プラグマ : http://perldoc.perl.org/sigtrap.html -- POSIX signal : http://perldoc.perl.org/POSIX.html - Cライブラリの解説(Linux JMan) -- signal(2) : http://www.linux.or.jp/JM/html/LDP_man-pages/man2/signal.2.html -- sigaction(2) : http://www.linux.or.jp/JM/html/LDP_man-pages/man2/sigaction.2.html -- sigprocmask(2) : http://www.linux.or.jp/JM/html/LDP_man-pages/man2/sigprocmask.2.html -- sigsetopts(3) : http://www.linux.or.jp/JM/html/LDP_man-pages/man3/sigsetops.3.html - 他、POSIX系のサンプルや"re-entrant"問題を扱っているHP -- http://www.nurs.or.jp/~sug/soft/super/signal.htm -- http://d.hatena.ne.jp/yupo5656/20060114/p1 * Perlでのシグナル操作はCライブラリの signal(3) ベース 前掲のperlipcで"signal(3)"で検索すれば見つかるが、Perlでのシグナル処理は基本的にsignal(3)をベースにしている。そのため、sigprocmask(2)やsigsetopts(3)を経由したシグナルのブロッキングはそのままではできない。(POSIXを利用すれば別だが、そうすると次にメモした"Deferred"シグナル機構を迂回してしまう。) シグナルのブロッキングについては、"local"を用いた巧妙な手法がperlipcに載っている。 sub sig_blocked { local $SIG{ALRM} = 'IGNORE'; &blocked_routine; } sub blocked_routine { # SIGALRMについてブロック中である } "local"により、%SIGの元の値はスタックに積まれ、sig_blockedを抜けると戻される。blocked_routine()中はSIGALRMを受信しても無視されるようになる。 * Perl 5.7.3 以降の"Deferred"シグナル機構(コード最適指向の遅延シグナル検出機構?) perlipcに専用の節が設けられているほど重要である。 つまり、Perl 5.7.3 以降については、%SIGを用いる限り、 '' Perlの内部処理中にシグナルハンドラに飛ぶような事は無くなった '' と言うことらしい。 たとえIOを処理中であっても、Perlは内部で '' 適当に区切りの良いところで '' シグナルが受信されたかチェックしており、もしIO読み書き中でも、シグナルハンドラ処理後ちゃんと再開してくれるらしい。内部的には、Perlはopコードを順繰りに読み進めているわけだが、ちょうどopコードの切れ目のタイミングでシグナルをチェックしてくれているらしい((これも幾つかの"safe point"の一例であり、他にもPerlが"safe point"と認めているタイミングで、シグナルのフラグをチェックしているようである。))。 これにより、例えばopコードそれ自体の処理中(メモリIOが発生するタイミングなど)で突然シグナルハンドラに飛んでしまう、というような事はなくなり、全般的に安定性の向上につながっているようだ。 * POSIX モジュールベースも利用可能(但し"Deffered"シグナルは意味無しに?) sigaction(2)系を使用したい場合、POSIXモジュールからクラスや関数が提供されている。詳細はPOSIXモジュールのperldocを参照。 但し、perlipcの"Deferred"シグナルの節でもきっちり釘を刺されているが、POSIXを使用する場合、%SIGによる"Deferred"シグナル機構の恩恵を享受できなくなる。つまりPerl内部処理中にシグナルハンドラに入ることによるメモリ・IOの不具合が発生しうるという点に注意する必要がある。 * 結局詳細は"Perl Cookbook"待ち? 載ってるかなあ・・・。Amazonに注文はしてありますが、まだ届いてないです。 #navi_footer|Perl|