Linux,waitpid,WNOHANG,子进程,僵尸

时间:2014-03-29 16:01:35

标签: linux process kill zombie-process waitpid

我将程序作为守护程序运行。

父进程只等待子进程,当它意外死,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));
  }
}

但是当使用-9信号杀死子进程时,子进程进入僵尸进程。

waitpid应该立即返回子进程的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>

这是父亲的罪行

父亲不会被卡住,等待4总是被召唤。

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回到了死孩子的pid。

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

为什么子进程不会立即退出?相反,它竟然变成了僵尸。

3 个答案:

答案 0 :(得分:2)

我终于发现在lsof深度跟踪期间有一些fd泄漏。

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

答案 1 :(得分:1)

在我看来,waitpid并没有立即返回子pid,因为该进程不可用。

此外,看起来您实际上希望您的代码执行此操作,因为您使用waitpid()选项指定NOHANG,这可以防止阻塞,基本上允许父级继续运行,如果子级pid是不可用。

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

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

答案 2 :(得分:0)

你可以简单地使用

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

而不是睡一会儿,然后再试一次。