Wednesday, 22 December 2010

Implementing a Process Timeout

I had a slightly unusual requirement to implement recently where I need to execute a command line process from Java + have it timeout if it didn't complete within a given timeframe.

Having considered a rather messy solution involving threads, joins, etc, I stumbled across the Executor framework that appeared in Java 1.5. Although the concepts seemed a little abstract at first, it provided a fairly elegant way of doing it:
public void executeCommand(String command, long timeoutInSeconds) throws IOException,
InterruptedException, ProcessException {
ExecutorService service = Executors.newSingleThreadExecutor();
Process process = Runtime.getRuntime().exec(command);
try {
Callable call = new CallableProcess(process);
Future future = service.submit(call);
int exitValue = future.get(timeoutInSeconds, TimeUnit.SECONDS);
if (exitValue != 0) {
throw new ProcessException("Process did not exit correctly");
}
}
catch (ExecutionException e) {
throw new ProcessException("Process failed to execute", e);
}
catch (TimeoutException e) {
process.destroy();
throw new ProcessException("Process timed out", e);
}
finally {
service.shutdown();
}
}

private class CallableProcess implements Callable {

private Process p;

public CallableProcess(Process process) {
p = process;
}

public Integer call() throws Exception {
return p.waitFor();
}
}

Best of all, it actually works. :-)