macrodef没有正确传达退出状态

时间:2014-12-14 15:37:52

标签: java ant

我正在调用使用macrodef定义的Ant任务,但我发现fail任务的退出状态未正确传达给shell。

以下是SSCCE:

Ant文件:

<project>

<macrodef name="ff">
    <sequential>
        <fail message="some failure" status="3"/>
    </sequential>
</macrodef>

<ff/>

</project>

调用:

$ ant 
Buildfile: /[...]/build.xml

BUILD FAILED
[...]build.xml:10: The following error occurred while executing this line:
[...]build.xml:5: some failure

Total time: 0 seconds

构建按预期失败;退出状态不正确:

$ echo $?
1

I.e Ant退出时状态为1而不是3.仅当fail任务包含在macrodef内时才会发生。

1 个答案:

答案 0 :(得分:3)

可以从the documentation of the fail task获取有关status属性的初步猜测:

  

使用指定的状态代码退出; 假设未捕获生成的异常 ,JVM将以此状态退出。

使用macrodef时发生了什么:BuildException任务抛出的fail正在抓住由macrodef。最终吞下退出代码的macrodef会抛出某种包装器异常

在调试模式下运行Ant时,您也可以从异常堆栈跟踪中看到这一点:

使用macrodef:

some failure
    at org.apache.tools.ant.taskdefs.Exit.execute(Exit.java:164)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.apache.tools.ant.Task.perform(Task.java:348)
    at org.apache.tools.ant.taskdefs.Sequential.execute(Sequential.java:68)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.apache.tools.ant.Task.perform(Task.java:348)
    at org.apache.tools.ant.taskdefs.MacroInstance.execute(MacroInstance.java:398)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.apache.tools.ant.Task.perform(Task.java:348)
    at org.apache.tools.ant.Target.execute(Target.java:390)
    at org.apache.tools.ant.Target.performTasks(Target.java:411)
    at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1399)
    at org.apache.tools.ant.Project.executeTarget(Project.java:1368)
    at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
    at org.apache.tools.ant.Project.executeTargets(Project.java:1251)
    at org.apache.tools.ant.Main.runBuild(Main.java:809)
    at org.apache.tools.ant.Main.startAnt(Main.java:217)
    at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
    at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)

注意堆栈跟踪中MacroInstance类(第398行)调用的方法。通过查看此行的Ant代码,您可以看到try-catch块捕获fail抛出的异常:

try {
    c.perform();
} catch (BuildException ex) {
    if (this.macroDef.getBackTrace()) {
        throw ProjectHelper.addLocationToBuildException(ex, getLocation());
    }

    ex.setLocation(getLocation());
    throw ex;
}

catch块中,以下行引发新异常

throw ProjectHelper.addLocationToBuildException(ex, getLocation());

导致原始BuildException的退出代码被忽略。

更进一步,我们可以看到,如果启用this.macroDef.getBackTrace(),则抛出此包装器异常。因此,该问题的解决方案是在macrodef中将backtrace参数设置为false

<macrodef name="ff" backtrace="false">
    <sequential>
        <fail message="some failure" status="3"/>
    </sequential>
</macrodef>