package com.spotify.spawn;
import java.lang.reflect.Method;
import java.util.Arrays;
import jnr.posix.POSIXFactory;
/**
* Subprocess trampoline. Takes the parent pid and the main class as the first two arguments. The rest of the
* arguments are passed on to the subprocess main class.
*/
class Trampoline {
private static final String[] EMPTY_ARGS = {};
public static void main(String[] args) throws Exception {
System.out.flush();
if (args.length < 2) {
System.err.println("invalid arguments: " + Arrays.toString(args));
System.exit(Subprocesses.INVALID_ARGUMENTS_EXIT_CODE);
return;
}
try {
final int ppid = Integer.valueOf(args[0]);
monitorParent(ppid);
final String main = args[1];
final String[] mainArgs = args.length > 2 ? Arrays.copyOfRange(args, 2, args.length) : EMPTY_ARGS;
final Class<?> mainClass = Class.forName(main);
final Method mainMethod = Subprocesses.findMain(mainClass);
if (mainMethod == null) {
System.err.println("Main method not found: " + main);
System.exit(Subprocesses.INVALID_ARGUMENTS_EXIT_CODE);
}
mainMethod.invoke(null, (Object) mainArgs);
} catch (Throwable e) {
e.printStackTrace();
System.exit(Subprocesses.EXCEPTION_EXIT_CODE);
}
}
private static void monitorParent(final int pid) {
Subprocesses.startDaemon(() -> {
while (true) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
continue;
}
int ppid = POSIXFactory.getPOSIX().getppid();
if (ppid != pid) {
// If we've been reparented, then the spawning parent is dead.
System.exit(Subprocesses.OK_EXIT_CODE);
}
}
});
}
}