Article 3989 of fj.unix: Path: news2.sra.co.jp!katsu From: katsu@sra.CO.JP (WATANABE Katsuhiro) Newsgroups: fj.unix Subject: Re: [Q] How to kill child process when parent died Supersedes: Date: 07 Oct 1998 01:53:10 GMT Organization: Software Research Associates, Inc., Japan Lines: 145 Message-ID: <6veom3$l6b$1@sranhh.sra.co.jp> References: <4qbule$ndq@news3.iij.ad.jp> <4qd81f$cuq@masamune.dais.is.tohoku.ac.jp> <31C8B099.1B4@psn.or.jp> NNTP-Posting-Host: sras49.sra.co.jp In-reply-to: Kosei Matsuura's message of Thu, 20 Jun 1996 16:35:58 GMT Originator: katsu@sras49 Xref: news2.sra.co.jp fj.unix:3989 あまりのフォローの遅さが議論の妨げになっていたらごめんなさい。 投稿時に化けた を supersedes します。 記事 <4qbule$ndq@news3.iij.ad.jp> で Kosei Matsuura さんいはく >  UNIX(AIX V4.1.4)のアプリケーションを作っていて問題が > 発生しました。UNIXの書籍を2冊読みましたが、対策法を見つけられませ > んでした。 >[現在のプログラム仕様] > 親プロセスと子プロセスの2つからなる。 >  この親子プロセス間に、定期通信はない。親は必要に応じて子へコマンドを > 送り、子はそれを待っている。 >  親プロセスの正常終了時には、親プロセスの終了時処理で、子プロセスに終 > 了コマンドを送り、子プロセスも終了させる。なお、子は親からの終了コマン > ドが来ない限り自発的に消滅はしない。 > > [問題点] > 親プロセスが異常終了したときに、子プロセスに終了通知を送る処理を実行 > できない。このため、子プロセスが消滅しないで取り残されてしまう(親プロ > セスIDが1(initプロセス)となった子プロセスが残る)。 > > [知りたいこと] >  子プロセスが取り残される現状を回避する方法。たとえば親プロセスの消滅 > を、子プロセスで知る方法など。 後述する方法が応用できる可能性は高いです。 記事 <4qd81f$cuq@masamune.dais.is.tohoku.ac.jp> で kabe@dais.is.tohoku.ac.jp さんいはく > >> 発生しました。UNIXの書籍を2冊読みましたが、対策法を見つけられませ > >> んでした。 > > ひどい本ですね。このあたりはUNIXの基本だと思うんですが。 私はそうは思いません。理由は以下の4点です。 [a] 完全な解決方法が与えられない可能性が高そうだ。 [b] 具体的に解決方法を与えている書籍や論文を実際に知らない。 [c] 過去に同様の議論が fj.unix で行われた際、完全な解決をみなかった。 [d] OSの実装(準拠している標準)によって解決法が異なりそうだ。 今回の議論が [a] を否定し、[b],[c] を覆すようなことがあれば嬉しいです。 > まず本当に終了通知が送れないのかどうか検討して下さい。 > SIGKILLで親を殺しているのでなければ方法はあるはずです。 > > *) atexit() をひっかけて親の死に際にwait()させる。 > *) データグラムではなくストリームにして、SIGPIPEをひっかける > (子が極端に多いとこれではだめか) > *) 子供の方で定期的にppidをポーリング(消極的) > *) 親子をひっくり返して常に子供が先に死ぬようにする > *) 単一プロセスでがんばる 1番目は意味がありません。atexit(3) で指定した関数は、exit(3) や main からの return など、正常終了の場合だけ呼び出されます。 2番目も、親子間に定期通信がないそうですから、無意味だと思います。 4番目5番目も、toy program でない限り、適用するのが困難でしょう。 私の考えでは、プロセスの親子関係には何か必然性があることが多いです。 記事 <31C8B099.1B4@psn.or.jp> で Sakaida さんいはく > 親プロセス側にシグナル処理をいれる方法が最も簡単ではないでしょうか。次のよ > 但し、kill -9 で kill されたプロセスはシグナルを検知できません。 SunOS や BSD 系など POSIX 準拠のOSならば、 ・親(や子)がよしんば SIGKILL で容赦なく殺される場合も考慮する ・親と子のソースコードを全く変更しない という条件下でも、関連する全部のプロセスを終了させる方法があります。 親子を監視する祖母プロセスを設けるという戦略です。以下の記事は、 私が昔に fj.unix に投稿したものを編集して、本質的な部分を抽出し、 誤りの修正を若干行ったものです。編集前の記事や議論の詳細は、 http://www.sra.co.jp/people/katsu/article/#killchild をご覧下さい。コード例も置いてあります。 ======== を編集 ==== From: katsu@sran14.sra.co.jp (Katsuhiro Watanabe) Newsgroups: fj.unix Subject: Re: Kill child process, when parent process died. Message-ID: Date: 9 Dec 91 06:01:40 GMT (1)プロセス間の親子関係を下のように構成する。 +---- +---- 親 ----+---- 子供達  祖母 ----+ +---- +---- 叔父 (2)祖母がプロセスグループリーダーになり、祖母、親、叔父、子供達の    プロセスグループを同一(仮に g)にする。 (3)祖母は wait(2) を繰り返し、その戻り値に対して以下を繰り返す。 if (親が死んだ) { killpg(g, SIG死ね); exit(1); } if (叔父が死んだ) 叔父を再起動する; (4)叔父は起動後、 kill(getpid(), SIGSTOP); pause();    しておく。一方で killpg(g, SIG死ね) するような SIGHUP の    ハンドラーを登録しておく。 こうしておけば、 (A)祖母が死ねば、停止している叔父に SIGHUP と SIGCONT が送られて    (BSD でプロセスが終了した際の振舞い)、叔父にみんな殺されます。 (B)親が死ねば、祖母の wait につかまって、祖母にみんな殺される。 (C)叔父が死んでも、祖母がもう一回生んでくれて正常な状態に戻る。 ということになります。 ======== を編集したもの終り ==== 親と子のソースコードは一切変更する必要がありません。 元記事の AIX V4 も POSIX 準拠のはずで、この方法が採用できる ことでしょう。一方で、System V の R3 以前を基にしたOS(独自の 修正をしていないもの)では、プロセス終了時の振舞い(例えば _exit(2))の仕様が違うので、動かないと思います。 *全ての* UNIX に適用できる戦略もあります。それは、専用の login shell を作って、それが親プロセスを起動して監視するというものです。 *全ての* UNIX は、login shell を何らかの形で実現しているはずです。 login shell (controlling process) の死は、foreground process group leader の親プロセスが SIGHUP を捕捉することで検出できるのが普通で、 そうでなかったとしても何らかの手段が用意されていると考えて間違い ありません。ただし、 ・どのOSでも戦略は共通だが、実際の機構や関数や概念が異なっており  (例えば、session のような概念は 4.3BSD や SVR3 にはない)  移植性のあるコードを書くのが困難。 ・親プロセスのソースを変更せねばならない。(SIGHUP ハンドラの登録) ・親プロセスの SIGHUP のハンドラはこの戦略用に予約されてしまう。 という欠点が予想されます。私には System V などの環境や知識が ないので、どなたか試した方がいたら顛末を教えてください。 -- 渡邊克宏@SRA