How can I cause a child process to exit when the parent does?
Asked Answered
P

10

50

I am launching a child process with ProcessBuilder, and need the child process to exit if the parent process does. Under normal circumstances, my code is stopping the child properly. However, if I cause the OS to kill the parent, the child will continue running.

Is there any way to "tie" the child process to the parent, such that it'll exit when the parent is killed?


Similar questions:

Paint answered 6/11, 2008 at 17:15 Comment(0)
P
20

There is no tie between a child process and its parent. They may know each others process ID, but there's no hard connection between them. What you're talking about a orphan process. And it's an OS level concern. Meaning any solution is probably platform dependent.

About the only thing I can think of is to have the child check its parents status periodically, exiting if the parent's shutdown. I don't think this would be all that reliable though.

Pouched answered 6/11, 2008 at 17:21 Comment(4)
Checking the parent's status periodically can be reliable if you're polling to see if the child's PPID becomes 1, since orphaned processes get a PPID of the init process. (PID=1)Superfine
If anyone is wondering, in Android systems pid seems to be 0 (process System pid) instead of 1, when parent dies.Divisor
I've just implemented this "parent status checking" with one simple improvement - I just pass the original parent_pid to children and they just check to see if the parent pid stays the same. So it should work regardless of init/systemd/whatever pid numerical value.Mazard
What If we launch some 3rd party process like Word, Excel. We can't code this child processes to pole its parent right ??Fraternity
C
45

While you cannot protect against a hard abort (e.g. SIGKILL on Unix), you can protect against other signals that cause your parent process to shut down (e.g. SIGINT) and clean up your child process. You can accomplish this through use of shutdown hooks: see Runtime#addShutdownHook, as well as a related SO question here.

Your code might look something like this:

String[] command;
final Process childProcess = new ProcessBuilder(command).start();

Thread closeChildThread = new Thread() {
    public void run() {
        childProcess.destroy();
    }
};

Runtime.getRuntime().addShutdownHook(closeChildThread); 
Creedon answered 7/11, 2008 at 16:58 Comment(2)
Runtime.getRuntime().addShutdownHook(new Thread(childProcess::destroy));Julianajuliane
For me in Groovy this was Process proc = cmd.execute() addShutdownHook { proc.destroy() }Kaplan
P
20

There is no tie between a child process and its parent. They may know each others process ID, but there's no hard connection between them. What you're talking about a orphan process. And it's an OS level concern. Meaning any solution is probably platform dependent.

About the only thing I can think of is to have the child check its parents status periodically, exiting if the parent's shutdown. I don't think this would be all that reliable though.

Pouched answered 6/11, 2008 at 17:21 Comment(4)
Checking the parent's status periodically can be reliable if you're polling to see if the child's PPID becomes 1, since orphaned processes get a PPID of the init process. (PID=1)Superfine
If anyone is wondering, in Android systems pid seems to be 0 (process System pid) instead of 1, when parent dies.Divisor
I've just implemented this "parent status checking" with one simple improvement - I just pass the original parent_pid to children and they just check to see if the parent pid stays the same. So it should work regardless of init/systemd/whatever pid numerical value.Mazard
What If we launch some 3rd party process like Word, Excel. We can't code this child processes to pole its parent right ??Fraternity
S
19

You can simply start a thread reading from System.in in the child process. If you are not writing to stdin of your child, nobody else will do and the thread will block "forever". But you will get an EOF (or an exception), if the parent process is killed or dies otherwise. So you can shutdown the child as well. (Child process started with java.lang.ProcessBuilder)

Stumpy answered 16/8, 2011 at 21:52 Comment(2)
This is a good solution. If reading is done in a thread. Remember to set thread deamon(true) or thread will stop program from shutting normally.Packaging
What is the overhead of this solution?Nibelung
H
9

Provide a hacker way which is similar with the answer from @tomkri and also provide the demo code.

If your child process do not need use input stream, just redirect child process input stream to its parent process's input stream. Then add a thread in child to always read input stream and when this thread can not read anything from input stream, this child process exits. So the parent process exits -> parent's input stream does not exist -> child's input stream does not exist -> child process exits.

Here is the demo code all in Java.

Parent Process:

package process.parent_child;

import java.io.File;
import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;

public class ParentProc {

    public static void main(String[] args) {
        System.out.println("I'm parent.");

        String javaHome = System.getProperty("java.home");
        String javaBin = javaHome + File.separator + "bin" + File.separator + "java";
        ProcessBuilder builder = new ProcessBuilder(javaBin, "process.parent_child.ChildProc");

        // Redirect subprocess's input stream to this parent process's input stream.
        builder.redirectInput(Redirect.INHERIT);
        // This is just for see the output of child process much more easily.
        builder.redirectOutput(Redirect.INHERIT);
        try {
            Process process = builder.start();
            Thread.sleep(5000);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Parent exits.");
    }
}

Child Process:

package process.parent_child;

import java.io.IOException;
import java.util.Scanner;

public class ChildProc {


    private static class StdinListenerThread extends Thread {

        public void run() {
            int c;
            try {
                c = System.in.read();
                while ( c != -1 ) {
                    System.out.print(c);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("\nChild exits.");
            System.exit(0);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        System.out.println("I'm child process.");
        StdinListenerThread thread = new StdinListenerThread();
        thread.start();
        Thread.sleep(10000);
    }
}

After run this parent process by the following command:

    java process.parent_child.ParentProc

You will see

    I'm parent.
    I'm child process.
    Parent exits.
    xmpy-mbp:bin zhaoxm$
    Child exits

Child process exits immediately when parent process exits.

Hydrastis answered 12/11, 2015 at 16:16 Comment(2)
nice solution, it was very helpful.Instrumental
This works nicely, and allows you to gracefully exit and avoid orphans of a child java process when the parent java process is terminated with a SIGKILL by Eclipse (for example).Dominion
E
5

As you've found the operating system allows you to get around this issue. Instead, create a resource shared by both processes. When the parent aborts the resource, the child reacts by shutting down. For example:

Create a thread with an server-side TCP/IP socket in accept mode on the parent on a random high number port. When the child starts, pass the port number as a parameter (environment variable, database entry, whatever). Have it create a thread and open that socket. The have the thread sit on the socket forever. If the connection ever drops, have the child exit.

or

Create a thread on parent that continually updates the update date on a file. (How often depends on how much granularity between kill and shutdown you need.) The child has a thread that monitors the update time of the same file. If it doesn't update after a specific interval, automatically shutdown.

Eyestalk answered 28/12, 2008 at 7:25 Comment(0)
F
2

For a single child processes you can manage this by inverting the child/parent relationship. See my answer to a later incarnation of this question.

Fara answered 28/12, 2008 at 6:17 Comment(0)
S
1

For windows, I came up with this polling hack:

static int getPpid(int pid) throws IOException {
    Process p = Runtime.getRuntime().exec("C:\\Windows\\System32\\wbem\\WMIC.exe process where (processid="+pid+") get parentprocessid");
    BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
    br.readLine();
    br.readLine();
    String ppid= br.readLine().replaceAll(" ","");
    return Integer.parseInt(ppid);
}
static boolean shouldExit() {
    try {
        String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
        int ppid = getPpid(Integer.parseInt(pid));
        /* pppid */ getPpid(ppid);
    } catch (Exception e) {
        return true;
    } 
    return false;
}
Swordbill answered 16/7, 2015 at 9:41 Comment(0)
E
0

Try to send a kill signal to the child process from the parent when the parent stops

Eleni answered 6/11, 2008 at 17:29 Comment(3)
Killing a process normally doesn't allow it any sort of clean up. Which is exactly the problem.Pouched
That depends on how you kill a process and under what OS. SIGTERM on Unixes allows the program to do cleanup, SIGKILL does not.Eclogite
You didn’t answer the “how” though; https://mcmap.net/q/25633/-how-can-i-cause-a-child-process-to-exit-when-the-parent-does did (and IMHO ought to become the accepted answer, too).Eiland
A
-1

As I tested, if the parent is killed, then the ppid of a child will become 1. So probably we can kill any processes that have ppid = 1.

Anomalistic answered 22/6, 2012 at 18:50 Comment(0)
C
-1

Once we have the process id (PID) of the parent we can kill all the child process. We can use the windows taskkill command to kill any process that was started by the corresponding PID.

You can find the PID based on your use-case from the following post: https://stackoverflow.com/Questions/4750470/how-to-get-pid-of-process-ive-just-started-within-java-program

Once you have your PID all you need to do is to ask the OS to kill the process for you by sending the following command: "taskkill /F /T /PID P_id". Here replace the P_id with your process id. Here /T kills all the processes in the process tree of the corresponding PID.

You can use java.lang.Runtime.exec function to execute the above command.

PS: This solution will only work for Windows OS.

Captious answered 26/12, 2020 at 0:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.