いくつかのサブプロセスを実行し、その出力を読み取る必要があるツールキットのモジュールを作成しています。ただし、ツールキットを使用するメイン プログラムは、いくつかのサブ プロセスを生成し、ゾンビ プロセスを取り除くためのSIGCHLD
呼び出しを行うシグナル ハンドラを設定することもあります。wait(NULL)
その結果、作成したサブプロセスが my 内で終了waitpid()
すると、シグナル ハンドラが呼び出される前に子プロセスが処理されるため、wait()
シグナル ハンドラ内の は次のプロセスが終了するまで待機します (これには永遠にかかる可能性があります)。Linux の実装ではファミリwait()
がSIGCHLD
. 私は試してみましpopen()
たposix_spawn()
両方とも同じ問題を抱えています。また、直接の子がすぐに存在するように double を使用しようとしましたが、受信後に呼び出されるfork()
ことはまだ保証できません。waitpid()
SIGCHLD
私の質問は、プログラムの他の部分が呼び出すシグナルハンドラーをセットアップする場合wait()
(おそらく呼び出す必要がありますが、それは私が制御できるものではありません)、ハンドラーwaidpid
を上書きせずに子プロセスを安全に実行する方法はありますか(SIGCHLD
一部のプログラムでは便利です)またはゾンビプロセス。
問題を示す小さなプログラムは次のとおりです (メイン プログラムは、waitpid() で直接待機している短いプログラムではなく、長期的な子プログラムの終了後にのみ終了することに注意してください):
#include <signal.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
static void
signalHandler(int sig)
{
printf("%s: %d\n", __func__, sig);
int status;
int ret = waitpid(-1, &status, 0);
printf("%s, ret: %d, status: %d\n", __func__, ret, status);
}
int
main()
{
struct sigaction sig_act;
memset(&sig_act, 0, sizeof(sig_act));
sig_act.sa_handler = signalHandler;
sigaction(SIGCHLD, &sig_act, NULL);
if (!fork()) {
sleep(20);
printf("%s: long run child %d exit.\n", __func__, getpid());
_exit(0);
}
pid_t pid = fork();
if (!pid) {
sleep(4);
printf("%s: %d exit.\n", __func__, getpid());
_exit(0);
}
printf("%s: %d -> %d\n", __func__, getpid(), pid);
sleep(1);
printf("%s, start waiting for %d\n", __func__, pid);
int status;
int ret = waitpid(pid, &status, 0);
printf("%s, ret: %d, pid: %d, status: %d\n", __func__, ret, pid, status);
return 0;
}