为什么在使用waitFor时终止JVM会同时终止其子进程?

4
如果没有使用waitFor,终止JVM对其子进程没有影响。下面是一个例子。
Bash脚本:
#!/usr/bin/env bash
echo "Sleeping..." > 'log'
sleep 30
echo "Wake up" >> 'log'

Java代码:

public class Code {
  public static void main(String[] args) throws Exception {
    Process process = Runtime.getRuntime().exec("./child.sh");
    // process.waitFor();
  }
}

在发出Java代码后,JVM立即终止。 ps -ef | grep 'child.sh' | grep -v grep 显示:

jing      3535  2761  0 13:47 pts/15   00:00:00 bash ./child.sh

30秒后,我检查当前目录中log文件的内容。内容如下:

Sleeping...
Wake up

以上grep命令现在没有显示任何内容。现在我取消注释process.waitFor()并重新编译Code.java。 运行java Code后,我使用上述grep命令验证child.sh子进程正在运行。 然后我发出Ctrl-C,JVM终止。 现在运行以上的grep命令不显示任何内容。 而log文件的内容保持不变:

Sleeping...

我查看了 Process 的 Javadoc,但是没有解释这个行为。然后我使用以下代码来检查 forkexeclpwaitpid 系统调用的行为。结果显示它们的行为相同。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

static void err_sys(const char* msg) {
  printf("%s\n", msg);
  exit(1);
}

int main(void) {
    pid_t   pid;

    if ((pid = fork()) < 0) {
        err_sys("fork error");
    } else if (pid == 0) {
        if (execlp("/home/jing/code/lintcode/child.sh", "child.sh", (char *)0) < 0)
            err_sys("execlp error");
    }

  if (waitpid(pid, NULL, 0) < 0)
    err_sys("wait error");

  exit(0);
}

我在Ubuntu 14.04上使用Oracle JDK 1.8。uname -a命令的输出结果如下:

Linux jinglin 3.13.0-108-generic #155-Ubuntu SMP Wed Jan 11 16:58:52 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

有人能解释一下waitForwaitpid的效果吗?

Process.waitFor()会让进程依赖于Java父进程吗?在MAC平台上提出了类似的问题。但是它缺少细节。因此我在这里为我的环境提出这个问题。

1个回答

3

waitPid() 没有什么特别之处,除了让父进程在前台保持运行。


如果你先进行 fork,然后等待子进程结束,你会得到一个(简化的)进程树结构:

─┬= 1 init
 └─┬= 2 bash --login
   └─┬= 3 java code
     └─── 4 bash child.sh

Java是终端中的前台进程,子进程在它的进程组中。

当您按下^C时,整个前台进程组都将被终止1


如果您等待,则首先您的进程树与上述相同。 Java进程终止,子进程成为进程树根下的一个子进程。

─┬= 1 init
 ├──= 2 bash --login
 └─── 4 bash child.sh

子进程执行完毕并正常终止。


1进程组收到SIGINT信号,其默认操作是终止。但是,可以安装不同的信号处理程序。


你确定吗?控制终端对于涉及的三个进程是相同的,并且它从不关闭。 - Grisha Levit
真的。但是它们是如何终止的呢? - Ingo
内核向终端会话中前台进程组发送SIGINT信号。 - Grisha Levit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接