当前位置: 首页 > 面试题库 >

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

葛昕
2023-03-14
问题内容

如果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平台上问类似的问题。但是它缺少细节。所以我在这里针对我的环境提出这个问题。


问题答案:

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



 类似资料:
  • 问题内容: 我想尽可能快地重复执行子过程。但是,有时该过程将花费很长时间,因此我想取消它。我使用signal.signal(…),如下所示: 但有时这段代码将尝试阻止下一轮执行。停止test / home / lu / workspace / 152 / treefit / test2超时/ bin / sh:/ home / lu / workspace / 153 / squib_driver

  • 问题内容: 子进程开始于 有没有办法确保在父异常终止时将其杀死?我需要在Windows和Linux上都能使用。 编辑: 如果存在使用其他启动进程的方法的解决方案,则可以放宽启动子进程的要求。 问题答案: 呵呵,我昨天自己在研究这个!假设您无法更改子程序: 在Linux上,可能是唯一可靠的选择。(如果绝对有必要终止子进程,那么您可能希望将终止信号设置为SIGKILL而不是SIGTERM;链接到的代码

  • 问题内容: 我从python脚本生成了5个不同的进程,如下所示: 我的问题是,当父进程(主脚本)以某种方式被杀死时,子进程继续运行。 当父进程被杀死时,有没有办法杀死这样生成的子进程? 编辑:我正在尝试: 但这似乎不起作用 问题答案: 我自己也遇到了同样的问题,我有以下解决方案: 打电话之前,您可以设置。然后如此处所述python.org multiprocessing 进程退出时,它将尝试终止其

  • 问题内容: 我的应用程序在Linux上作为后台进程运行。当前在“终端”窗口的命令行中启动。 最近,一个用户执行该应用程序一段时间后,它神秘地死了。文本: 被杀 在航站楼上。这发生了两次。我问其他终端是否有人使用kill命令杀死进程?没有。 Linux在什么情况下会决定终止我的进程?我相信外壳程序显示为“ killed”,因为该进程在收到kill(9)信号后就死了。如果Linux发送了kill信号,

  • 我有一个用PHP编写的守护进程(不是最好的语言,但与我一起工作),它用于从队列接收作业,并在需要完成作业时处理它们。对于每个新作业,我使用pcntl_fork()将作业分叉到子进程中。在这个子进程中,我然后使用proc_open()执行用于音频转码的长时间运行的系统命令,完成后直接返回到子进程。作业完成后,子进程退出并由父进程清理。 为了保持这个守护进程始终运行,我使用upstart。这是我的暴发

  • 问题内容: 我有一个运行bash脚本的詹金斯工作。 在bash脚本中,我有效地执行了两个操作,例如 但是如果手动中止了作业,则该作业仍然有效(如节点计算机上的a所示)。我无法使用陷印等等,因为如果jenkins发送信号(陷印不适用于),那将不起作用。 如果可以将此作业配置为简单地杀死它产生的 所有 进程,那将是理想的,我该怎么做? 问题答案: 实际上,默认情况下,Jenkins具有一个名为 Pro