Linux,waitpid,WNOHANG,subprocess,僵尸

我作为守护进程运行我的程序。

父进程只等待subprocess,当它意外死了,fork再等待。

for (; 1;) { if (fork() == 0) break; int sig = 0; for (; 1; usleep(10000)) { pid_t wpid = waitpid(g->pid[1], &sig, WNOHANG); if (wpid > 0) break; if (wpid < 0) print("wait error: %s\n", strerror(errno)); } } 

但是当subprocess被-9信号杀死时,subprocess就进入僵尸进程。

waitpid应该立即返回subprocess的PID!
但是waitpid在大约90秒后得到了PID号码,

 cube 28139 0.0 0.0 70576 900 ? Ss 04:24 0:07 ./daemon -d cube 28140 9.3 0.0 0 0 ? Zl 04:24 106:19 [daemon] <defunct> 

这是父亲的分寸

父亲没有被卡住,总是等待。

 strace -p 28139 Process 28139 attached - interrupt to quit restart_syscall(<... resuming interrupted call ...>) = 0 wait4(28140, 0x7fff08a2681c, WNOHANG, NULL) = 0 nanosleep({0, 10000000}, NULL) = 0 wait4(28140, 0x7fff08a2681c, WNOHANG, NULL) = 0 

大约90秒之后,父亲得到了SIGCHILD,然后等4回到了死亡的小孩的孩子。

 --- SIGCHLD (Child exited) @ 0 (0) --- restart_syscall(<... resuming interrupted call ...>) = 0 wait4(28140, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGKILL}], WNOHANG, NULL) = 28140 

为什么subprocess不能立即退出? 相反,它竟然变成了僵尸。

它在我看来像waitpid没有立即返回的孩子pid只是因为该进程不可用。

此外,它看起来像你实际上希望你的代码这样做,因为你指定了与NOHANG选项的waitpid() ,这防止阻塞,基本上允许家长继续如果孩子PID不可用。

也许你的过程使用你没有想到的东西? 你可以跟踪它的活动,看看你是否找到了瓶颈?

这是一个非常有用的链接,可以帮助你: http : //infohost.nmt.edu/~eweiss/222_book/222_book/0201433079/ch08lev1sec6.html

我终于发现在lsof的深度追踪过程中有一些fd泄漏。

FD泄漏修复后,问题消失了。

你可以简单地使用

  for (;;) { pid_t wpid = waitpid(-1, &sig, 0); if (wpid > 0) break; if (wpid < 0) print("wait error: %s\n", strerror(errno)); } 

而不是睡一会儿再试一次。