親プロセスは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)

日本語がかなり分かりづらいので,要約するとこういうロジックのような気がする.

  1. SVR4では,制御端末が割り振られていないセッションリーダが端末をオープンしようとすると,自動的に制御端末が付与されてしまう
  2. これはマズイ!
  3. O_NOCTTYフラグを指定すれば防げるけど,忘れたらマズイよね
  4. SVR4の特性を発動させないためには,孫プロセス (非セッションリーダ) つくればよい.終.


でも,まぁ,現代だったらSolarisじゃなければ気にしなくてよい気がする...もちろん,ポータブルなコードを書く時には大切ですけれど.
僕の中では,double forkする理由はこれでファイナルアンサーなので,違う答えをご存知の方がいれば教えてください.

Reference

回答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を忘れるとゾンビプロセスが発生する理由がまだわかっていない(´・ω・`).あとでこっそり勉強しよう.