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;
}
}
}
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
.
I solved this problem by creating two extra batch files (not very nice, but it works):
Content of file myant.bat
:
call ant2.bat %*
Content of file ant2.bat
:
call ant.bat %*
if errorlevel 1 (goto ERROR_EXIT)
exit /B 0
:ERROR_EXIT
exit /B 1
Now I can call myant.bat
as a Process
from java and I get the correct exit value.
Sorry, I cannot say why this works. It's simply the result of a many many tries.
A quick patch is adding the following at the end of ANT.BAT file:
exit /b %ANT_ERROR%
This problem has long existed and fixed recently. Refer to Bug 41039.
It should be ready in ANT release 1.8.2 or later.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With