如果使用waitFor,为什么kill JVM也会终止其子进程? [英] Why does killing JVM also terminates its child process if waitFor has been used?
问题描述
如果未使用 waitFor
,则终止JVM对其子进程没有影响。这是一个例子。
If waitFor
is not used, killing JVM has no effect on its child process. Here is an example.
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
显示:
After Java Code
is issued, JVM terminates immediately. And ps -ef | grep 'child.sh' | grep -v grep
shows:
jing 3535 2761 0 13:47 pts/15 00:00:00 bash ./child.sh
然后在30秒后检查<$ c的内容$ c> log 当前目录中的文件。内容为:
Then after 30 seconds, I check the content of log
file in the current directory. The content is:
Sleeping...
Wake up
上面的 grep
命令现在什么都没有显示。现在我取消注释 process.waitFor()
并重新编译 Code.java
。运行 java Code
后,我使用上面的 grep
命令来验证 child.sh
子进程正在运行。然后我发出 Ctrl-C
,JVM终止。现在运行上面的 grep
命令什么都不显示。 log
文件的内容保持为:
And the above grep
command shows nothing now. Now I uncomment process.waitFor()
and recompile Code.java
. After I run java Code
, I use the above grep
command to verify that child.sh
child process is running. Then I issue Ctrl-C
, JVM terminates. Now running the above grep
command shows nothing. And the content of log
file stays as:
Sleeping...
我检查了处理
的Javadoc没有解释这种行为。然后我使用以下代码检查 fork
, execlp
和 waitpid 的行为code>系统调用。它显示了相同的行为。
I have checked Process
's Javadoc which does not explain this behavior. Then I use the following code to check the behavior of fork
, execlp
and waitpid
system calls. And it shows the same behavior.
#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
产生:
I am using Oracle JDK 1.8 on Ubuntu 14.04. uname -a
produces:
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
的影响吗?
Can anyone give an explanation about this effect of waitFor
and waitpid
?
Process.waitFor()是否使进程依赖于java父级?在MAC上提出类似的问题平台。但它缺乏细节。所以我在这里向我的环境提出这个问题。
Does Process.waitFor() make the process reliant on the java parent? asks a similar problem on MAC platform. But it lacks details. So I ask this question for my environment here.
推荐答案
waitPid()没什么特别的
,除了你将父进程保留在前台之外。
There's nothing special about waitPid()
, other than the fact that you keep the parent process in the foreground.
如果你分叉和然后等待孩子完成,你有一个(简化的)过程树,如下所示:
If you fork and then wait for the child to finish, you have a (simplified) process tree like this:
─┬= 1 init
└─┬= 2 bash --login
└─┬= 3 java code
└─── 4 bash child.sh
java
是终端中的前台进程,子进程在其进程组中。
java
is the foreground process in the terminal and the child is in its process group.
当你点击^ C时,整个前台进程组被终止。 1
When you hit ^C the entire foreground process group gets terminated.1
如果不等待,那么首先您的进程树与上面的进程树相同。 java
进程终止,子进程成为进程树根处的进程的子进程。
If you don't wait, then at first your process tree is the same as the one above. The java
process terminates and the child process becomes a child of the process at the root of the process tree.
─┬= 1 init
├──= 2 bash --login
└─── 4 bash child.sh
子进程完成执行并正常终止。
The child process finishes executing and terminates normally.
1 进程组收到一个SIGINT,默认操作将终止。但是,可以安装不同的信号处理程序。
1The process group receives a SIGINT, for which the default action is to terminate. However, a different signal handler may be installed.
这篇关于如果使用waitFor,为什么kill JVM也会终止其子进程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!