Suppose I have a process which spawns exactly one child process. Now when the parent process exits for whatever reason (normally or abnormally, by kill, ^C, assert failure or anything else) I want the child process to die. How to do that correctly?
Some similar question on stackoverflow:
- (asked earlier) How can I cause a child process to exit when the parent does?
- (asked later) Are child processes created with fork() automatically killed when the parent is killed?
Some similar question on stackoverflow for Windows:
If you're unable to modify the child process, you can try something like the following:
This runs the child from within a shell process with job control enabled. The child process is spawned in the background. The shell waits for a newline (or an EOF) then kills the child.
When the parent dies--no matter what the reason--it will close its end of the pipe. The child shell will get an EOF from the read and proceed to kill the backgrounded child process.
Inspired by another answer here, I came up with the following all-POSIX solution. The general idea is to create an intermediate process between the parent and the child, that has one purpose: Notice when the parent dies, and explicitly kill the child.
This type of solution is useful when the code in the child can't be modified.
There are two small caveats with this method:
As an aside, the actual code I'm using is in Python. Here it is for completeness:
This solution worked for me:
This was for a worker-type process whose existence only made sense when the parent was alive.
Even though 7 years have passed I've just run into this issue as I'm running SpringBoot application that needs to start webpack-dev-server during development and needs to kill it when the backend process stops.
I try to use
Runtime.getRuntime().addShutdownHook
but it worked on Windows 10 but not on Windows 7.I've change it to use a dedicated thread that waits for the process to quit or for
InterruptedException
which seems to work correctly on both Windows versions.In case it is relevant to anyone else, when I spawn JVM instances in forked child processes from C++, the only way I could get the JVM instances to terminate properly after the parent process completed was to do the following. Hopefully someone can provide feedback in the comments if this wasn't the best way to do this.
1) Call
prctl(PR_SET_PDEATHSIG, SIGHUP)
on the forked child process as suggested before launching the Java app viaexecv
, and2) Add a shutdown hook to the Java application that polls until its parent PID equals 1, then do a hard
Runtime.getRuntime().halt(0)
. The polling is done by launching a separate shell that runs theps
command (See: How do I find my PID in Java or JRuby on Linux?).EDIT 130118:
It seems that was not a robust solution. I'm still struggling a bit to understand the nuances of what's going on, but I was still sometimes getting orphan JVM processes when running these applications in screen/SSH sessions.
Instead of polling for the PPID in the Java app, I simply had the shutdown hook perform cleanup followed by a hard halt as above. Then I made sure to invoke
waitpid
in the C++ parent app on the spawned child process when it was time to terminate everything. This seems to be a more robust solution, as the child process ensures that it terminates, while the parent uses existing references to make sure that its children terminate. Compare this to the previous solution which had the parent process terminate whenever it pleased, and had the children try to figure out if they had been orphaned before terminating.I'm trying to solve the same problem, and since my program must run on OS X, the Linux-only solution didn't work for me.
I came to the same conclusion as the other people on this page -- there isn't a POSIX-compatible way of notifying a child when a parent dies. So I kludged up the next-best thing -- having the child poll.
When a parent process dies (for any reason) the child's parent process becomes process 1. If the child simply polls periodically, it can check if its parent is 1. If it is, the child should exit.
This isn't great, but it works, and it's easier than the TCP socket/lockfile polling solutions suggested elsewhere on this page.