in src/main/java/com/spotify/fmt/ForkingExecutor.java [165:205]
void start() {
if (process != null) {
throw new IllegalStateException();
}
log.debug("serializing closure");
try {
Serialization.serialize(f, closureFile);
} catch (SerializationException e) {
throw new RuntimeException("Failed to serialize closure", e);
}
final String classPathArg = String.join(File.pathSeparator, classpath);
final ProcessBuilder processBuilder =
new ProcessBuilder(java.toString(), "-cp", classPathArg).directory(workdir.toFile());
// Custom jvm args
javaArgs.forEach(processBuilder.command()::add);
// Trampoline arguments
processBuilder.command().add(Trampoline.class.getName());
processBuilder.command().add(closureFile.toString());
processBuilder.command().add(resultFile.toString());
processBuilder.command().add(errorFile.toString());
processBuilder.environment().putAll(environment);
log.debug(
MessageFormat.format(
"Starting subprocess: environment={0}, command={1}, directory={2}",
processBuilder.environment(), processBuilder.command(), processBuilder.directory()));
try {
process = processBuilder.start();
} catch (IOException e) {
throw new RuntimeException(e);
}
// Copy std{err,out} line by line to avoid interleaving and corrupting line contents.
executor.submit(() -> copyLines(process.getInputStream(), System.out));
executor.submit(() -> copyLines(process.getErrorStream(), System.err));
}