You can do it with a bit of C, as long as you're not worried about a few conditions, and understand that it will have limitations.
The prctl(PR_SET_PDEATHSIG, …)
system call is part of the linux kernel, and has a couple of rules - it doesn't survive fork()
, it doesn't survive exec()
into a setuid/setgid binary.
limitations are:
- This is a simple program, it will kill things horribly if you launch something else from the child process unless you put in some limits.
- it won't work across executable models (e.g. 32->64bit) which is relatively rare
- it won't work with statically linked binaries (rare)
With these limitations in mind, we can make a small preload library from some C
that will invoke this system call. So, for example:
#include <sys/prctl.h>
#include <sys/types.h>
#include <signal.h>
__attribute__((constructor))
static void on_load() {
prctl(PR_SET_PDEATHSIG, SIGTERM);
}
compiled using gcc -fPIC -shared -o term_death.so term_death.c
when you use the LD_PRELOAD
environment variable with the full path to this binary, any programs that are launched will be sent a SIGTERM
when their parent process is killed.
This is the setup from the C side - we now have a helper library that will allow the behaviour you're asking for.
Getting this to work from the java side.
We need to inject the full path to the .so into the LD_PRELOAD
environment variable for the ProcessBuilder, so something like:
ProcessBuilder pb = new ProcessBuilder();
Map<String, String> env = pb.environment();
env.put("LD_PRELOAD", "/home/me/development/experiments/term_death.so");
again, you need to specify the path to the .so
so that it can be loaded.
When you pb.start()
it will inherit the LD_PRELOAD
environment variable. On loading the executable, it runs the on_load
code (because it's marked as a constructor) and says that the process will receive a SIGTERM
when the parent process terminates.
This is somewhat ugly, but should address the issue.