親プロセスは2度死ぬ - デーモン化に使うダブルforkの謎
デーモンプロセスを作る場合には,教科書によく書かれている2度forkは不要ではないか? ということを以前の記事に書いた.
確かにBSDのdaemon(3) のコードでは,forkは1回しか呼んでいない.
「きっとプレセスがセッションリーダだと不都合があるのだろう.でもなぜ?」 というのがopen questionだった.
それに対する答えを「詳解UNIXプログラミング」[1] に見つけた.
SVR4においては,この時点でforkを再度呼び,親を終了することを勧める人がいる.
2番目の子がデーモンとして動作する.これは,デーモンはセッションリーダではなく,
SVR4の規則 (9.6節) から,セッションリーダでなければ制御端末を取得できない,ということを保証する.
あるいは,制御端末を取得しないことを確実にするには,端末装置をオープンする度にO_NOCTTYを指定する.
([1] p.403)
SVR4の規則ってなんだ?
SVR4では,制御端末を割り付けられていないセッションにおいて,
セッションリーダが最初の端末装置をオープンしたときに,セッションに制御端末を割り付ける.
これは,セッションリーダがopenを呼ぶ際,O_NOCTTYフラグ (3.3節) を指定しないことを仮定している.
([1] p.239)
日本語がかなり分かりづらいので,要約するとこういうロジックのような気がする.
- SVR4では,制御端末が割り振られていないセッションリーダが端末をオープンしようとすると,自動的に制御端末が付与されてしまう
- これはマズイ!
- O_NOCTTYフラグを指定すれば防げるけど,忘れたらマズイよね
- SVR4の特性を発動させないためには,孫プロセス (非セッションリーダ) つくればよい.終.
でも,まぁ,現代だったらSolarisじゃなければ気にしなくてよい気がする...もちろん,ポータブルなコードを書く時には大切ですけれど.
僕の中では,double forkする理由はこれでファイナルアンサーなので,違う答えをご存知の方がいれば教えてください.
Reference
- [1] W・リチャード・スティーヴンス著,大木敦雄訳「詳解UNIXプログラミング」ピアソン・エデュケーション (2000).
回答2: ゾンビプロセス発生を抑えるため
Twitter TL上で別の回答を発見! (実はこの回答を見つけて,あわててずっとdraftバージョンだった上記の記事をupしたというワケです)
double forkになっている理由!waitを忘れるとゾンビプロセスが発生するから。ずっと疑問だったんだけど納得した。 #tork03
by kuenishi (http://twitter.com/kuenishi/status/9768707555)
親プロセスが死ぬと子プロセスがinitの養子になる。initはwaitしまくってるのでゾンビプロセスを回収できている。 #tork03
by kuenishi (http://twitter.com/kuenishi/status/9768731754)
と,引用したはいいけれど,waitを忘れるとゾンビプロセスが発生する理由がまだわかっていない(´・ω・`).あとでこっそり勉強しよう.