小编典典

如果使用了waitFor,为什么杀死JVM也会终止其子进程?

java

如果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 Code发出后,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-CJVM终止。现在,运行上面的grep命令不会显示任何内容。log文件内容保持为:

Sleeping...

我已经检查了Process不能解释此行为的Javadoc。然后我用下面的代码来检查的行为forkexeclp以及
waitpid系统调用。它显示了相同的行为。

#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

谁能解释waitFor和的这种影响waitpid

Process.waitFor()是否使进程依赖于Java父级?在MAC平台上问类似的问题。但是它缺少细节。所以我在这里针对我的环境提出这个问题。


阅读 225

收藏
2020-11-19

共1个答案

小编典典

除了waitPid()您将父进程放在前台这一事实之外,没有什么特别的。


如果分叉,然后等待子进程完成,则将有一个(简化的)进程树,如下所示:

─┬= 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,其默认操作将终止。但是,可能会安装其他信号处理程序。

2020-11-19