package io.fathom.auto.processes;
import io.fathom.auto.TimeSpan;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.io.Files;
public class Processes {
private static final Logger log = LoggerFactory.getLogger(Processes.class);
public static ProcessExecution run(ProcessBuilder pb, TimeSpan timeout) throws IOException {
File stdoutFile = null;
File stderrFile = null;
Process process = null;
try {
stdoutFile = File.createTempFile("stdout", "log");
stderrFile = File.createTempFile("stderr", "log");
pb.redirectOutput(stdoutFile);
pb.redirectError(stderrFile);
log.info("Running process: " + Joiner.on(" ").join(pb.command()));
process = pb.start();
Integer exitCode = null;
try {
exitCode = Processes.waitForExit(process, timeout);
} catch (TimeoutException e) {
log.warn("Timeout while running process");
}
String stdout = Files.toString(stdoutFile, Charsets.UTF_8);
String stderr = Files.toString(stderrFile, Charsets.UTF_8);
return new ProcessExecution(exitCode, stdout, stderr);
} finally {
if (process != null) {
process.destroy();
}
if (stdoutFile != null) {
stdoutFile.delete();
}
if (stderrFile != null) {
stderrFile.delete();
}
}
}
public static int waitForExit(Process process, TimeSpan timeout) throws TimeoutException {
Worker worker = new Worker(process);
worker.start();
timeout.join(worker);
Integer exit = worker.getExitCode();
if (exit != null) {
return exit;
} else {
throw new TimeoutException();
}
}
private static class Worker extends Thread {
private final Process process;
private Integer exitCode;
private Worker(Process process) {
this.process = process;
}
@Override
public void run() {
try {
int exitCode = process.waitFor();
setExitCode(exitCode);
} catch (InterruptedException ignore) {
return;
}
}
public synchronized Integer getExitCode() {
return exitCode;
}
public synchronized void setExitCode(Integer exitCode) {
this.exitCode = exitCode;
}
}
}