Why does ant.bat not return an error status when run programmatically?
ant, exec, fork, java
Solution
I solved this problem by creating a single batch file (quite a bit nicer than the above but still mysterious):
Content of file `myant.bat`:
@echo off
rem RunAnt simply calls ant -- correctly returns errorlevel for callers
call ant.bat %*
crucially, without any code whatsoever after the `call`.
Problem
When I run ant from the command-line, if I get a failure, I get a non-zero exit status ($? on UNIX, %ERRORLEVEL% on Windows). But we have a Java program which is running ant (through ProcessBuilder), and when ant fails, on Windows we cannot get the exit status. I just verified this with this simple ant test file: ``` <project name="x" default="a"> <target name="a"> <fail/> </target> </project> ``` On UNIX, running ant prints a failure message, and echoing $? afterward prints 1. On Windows, running ant or ant.bat prints a failure message, and echoing %ERRORLEVEL% afterward prints 1. Now, using the test program below: On UNIX, java Run ant prints a failure message, and echoing $? afterward prints 1. On Windows, java Run ant can't find a program named ant to run, but java Run ant.bat prints a failure message, yet echoing %ERRORLEVEL% afterward prints 0. What gives? We're relying on being able to check the exit status after running ant. We were, anyway. Why can't we rely on this, programmatically? Test program: ``` import java.io.*; public class Run { public static void main(String[] args) throws IOException, InterruptedException { ProcessBuilder pb = new ProcessBuilder(args); Process p = pb.start(); ProcThread stdout = new ProcThread(p.getInputStream(), System.out); ProcThread stderr = new ProcThread(p.getErrorStream(), System.err); stdout.start(); stderr.start(); int errorLevel = p.waitFor(); stdout.join(); stderr.join(); IOException outE = stdout.getException(); if (outE != null) throw(outE); IOException errE = stdout.getException(); if (errE != null) throw(errE); System.exit(errorLevel); } static class ProcThread extends Thread { BufferedReader input; PrintStream out; IOException ex; ProcThread(InputStream is, PrintStream out) { input = new BufferedReader(new InputStreamReader(is)); this.out = out; } @Override public void run() { String line; try { while ((line = input.readLine()) != null) out.println(line); } catch (IOException e) { setException(e); } } private void setException(IOException e) { this.ex = e; } public IOException getException() { return ex; } } } ```