Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Process.waitFor() make the process reliant on the java parent? [duplicate]

Tags:

java

linux

jvm

If waitFor is not used, killing JVM has no effect on its child process. Here is an example.

Bash script:

#!/usr/bin/env bash
echo "Sleeping..." > 'log'
sleep 30
echo "Wake up" >> 'log'

Java code:

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

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

Then after 30 seconds, I check the content of log file in the current directory. The content is:

Sleeping...
Wake up

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...

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);
}

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

Can anyone give an explanation about this effect of waitFor and waitpid?

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.

like image 682
Jingguo Yao Avatar asked Nov 21 '22 20:11

Jingguo Yao


1 Answers

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 is the foreground process in the terminal and the child is in its process group.

When you hit ^C the entire foreground process group gets terminated.1


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.


1The process group receives a SIGINT, for which the default action is to terminate. However, a different signal handler may be installed.

like image 124
Grisha Levit Avatar answered Dec 06 '22 09:12

Grisha Levit