4

私は、クライアント コードに統合されるライブラリ (C++) に取り組んでいます。この lib はいくつかの子プロセスを生成し、(何らかの理由で) 死ぬとすぐにそれらを再生成するためにそれらを監視する必要があります。これらの子プロセスを生成するには、vfork と exec を使用する必要があります。

シグナル ハンドラーを使用して SIGCHLD を処理し、waitpid を呼び出して、どの子が死んでいるかを検出する必要があることはわかっています。ただし、ユーザー コードは同じ考え方を使用して、独自の子プロセスを処理している可能性があります。

waitpid を呼び出すと、停止した可能性のあるすべての子プロセスに関する情報が取得されます (私のものかどうかに関係なく)。死にゆくプロセスが私のものなら、問題ありません... 幸せなケースです。ただし、それがユーザーからのものである場合、既に waitpid を呼び出しているため、ユーザーはそれに関する情報を取得していません。

どうすればそれを回避できますか?

私の最初のアイデアは、プロセス グループを使用することです。初めて fork すると、子 pid を取得して、プロセス グループ ID として保存します。私が作成する各子は、そのグループをこの pid に設定します。皆さん、それは良い選択だと思いますか? (私はそれに問題があります)。

私の 2 番目のアイデアは、シグナル ハンドラーを元のハンドラーにリセットする (または単に呼び出す) ことです。シグナルを再発生させると、元のハンドラーがそれを取得できるようになります。その後、シグナルハンドラを再インストールする必要があります。それは良い選択でしょうか?

3 つ目の選択肢は、INFO (拡張シグナル ハンドラー) を使用することです。瀕死のプロセスの pid は info 構造体で利用できると思います。これが私の子供の 1 人なら、そのために waitpid を呼び出しますが、それで問題ありません。それが私のものでない場合は、元のシグナルハンドラーを呼び出します。それは良い選択でしょうか?

最後に 1 つだけ補足質問をします。元のシグナル ハンドラーを呼び出せるようにするには、常にそれらを復元してシグナルを再生成する必要がありますか、それとも関数呼び出しとして呼び出すだけで十分ですか?

どうもありがとうございました。

4

3 に答える 3

1

汎用ライブラリ(サードパーティ用)の場合は、そのような構成を避けるようにしてください。その使用が避けられない場合は、信号の処理を非常に注意深く文書化してください。

libとリンクしているプログラムがシグナルで再生される場合、多くの複雑な状況が発生する可能性があり、libは、予期しない方法でプログラムに影響を与えることなく、それらすべてを正しく処理する機会がありません。プログラムに複数のスレッドがあるか、そうでない他のシグナルを処理する可能性があることを考慮してください。いずれの場合も、プログラムはSIGCHILD同時にのシグナル処理を変更し、ロジックを壊す可能性があります。

おそらく、libで関数を提供し、シグナルSIGCHILD(作成したPIDの場合)が来たときにそれを呼び出すようにプログラムの責任を負わせて、プログラムが自由にシグナルを希望どおりに処理できるようにする方がよい場合があります。

于 2012-05-30T06:28:50.800 に答える
1

もう 1 つのオプションは、最初に 1 つの子プロセスを生成することです。これは、任意の IPC メカニズムを介してメイン プロセスと通信します。次に、その新しいプロセス内から複数の子プロセスを生成します。これにより、子プロセスの終了方法を完全に制御できます。

于 2012-05-29T22:13:47.633 に答える
0

この投稿は、私の解決策を明確にするためのものです。

メイン プロセスでシグナル ハンドラを使用しないことにしました。必要でない限り、ライブラリはシグナルを処理すべきではありません。

メイン プロセスから、自分自身をデーモンに変える別のバイナリを呼び出すパイプを作成します。このようにして、それによって生成されたプロセスはメインプロセスの子にはなりません。

デーモンにするには、フォークするだけです。フォークの親は子の PID を出力するだけなので、メイン プロセスは (パイプを介して) それを取得できます。子プロセスは umask をゼロに設定し、新しい SID を作成し、現在のディレクトリを "/" に変更し、STDIN、STDOUT、および STDERR を (すべて /dev/null に) 再度開きます。このようにして、子供はデーモンになります。

このデーモンは、すべてのプロセスを生成する責任があります。それらのすべて (デーモンを含む) は、ソケットを使用してメイン プロセスと通信します。

メイン プロセスは、デーモンにシグナルを送信します (デーモンとそのすべての子を閉じるには SIGINT、事前定義されたアクションに SIGUSER1 と 2 を送信します)。

ここで助けてくれたみんなに感謝します。

于 2012-06-01T02:35:57.480 に答える