Summary
After the #598 fork NPE fix, ant <java fork="true"> now runs the target class, but the build never completes and the serial shell wedges. BUILD SUCCESSFUL never appears; the forked process never terminates.
Repro
On a running JNode (all-plugins) with the lite ISO (commit 8c1f536):
<project default="main">
<target name="compile">
<mkdir dir="classes"/>
<javac srcdir="." destdir="classes" includeantruntime="false"/>
</target>
<target name="main" depends="compile">
<echo message="FORK-TEST-START"/>
<java classname="Hi" classpath="classes" fork="true">
<arg value="forked-arg"/>
</java>
</target>
</project>
public class Hi {
public static void main(String[] args) {
System.out.println("HELLO-STDOUT-JAVA");
System.out.println("ARG:" + (args.length > 0 ? args[0] : "none"));
}
}
Run ant via the serial console. Observed output:
compile:
[mkdir] Created dir: /jnode/tmp/anttest/classes
[javac] Compiling 1 source file to /jnode/tmp/anttest/classes
main:
[echo] FORK-TEST-START
[java] HELLO-STDOUT-JAVA
[java] ARG:forked-arg
[java] java.lang.NullPointerException: NPE at address 3883706)
[java] at org.apache.tools.ant.taskdefs.StreamPumper.run(StreamPumper.java:106)
[java] at java.lang.Thread.run(Thread.java)
[java] at org.jnode.vm.scheduler.VmThread.runThread(VmThread.java:764)
The forked class executes (its System.out appears), but ant never prints BUILD SUCCESSFUL and the shell never returns (Process.waitFor() on the parent side blocks forever; the serial agent must be interrupted).
Root cause
VmProcess never terminates. VmProcess.ProcessRunner.run() (core/src/core/org/jnode/vm/VmProcess.java:352-372) returns after mainMethod.invoke(...) but never calls VmProcess.exit(...). The running flag stays true, so Process.waitFor() (same file, ~331-340) blocks indefinitely.
- Streams are never assigned. The
VmProcess constructor (~64-104) sets System.in/out/err if null but never assigns the instance fields in, out, err (declared ~55-59). So getInputStream()/getErrorStream()/getOutputStream() return null, and ant's StreamPumper (which wraps proc.getInputStream() in a BufferedReader) throws the NPE above.
Expected behavior
<java fork="true"> should complete the process lifecycle: when the forked main() returns, the child VmProcess should exit (running=false, exitValue=0, notify waiters) so waitFor() returns and ant prints BUILD SUCCESSFUL / Total time and control returns to the shell. Options for the streams: either wire the child's System.out/err to in-memory pipes that the parent process reads (true stream capture), or at minimum return non-null streams so StreamPumper does not NPE.
Environment
Summary
After the #598 fork NPE fix, ant
<java fork="true">now runs the target class, but the build never completes and the serial shell wedges.BUILD SUCCESSFULnever appears; the forked process never terminates.Repro
On a running JNode (all-plugins) with the lite ISO (commit 8c1f536):
Run
antvia the serial console. Observed output:The forked class executes (its
System.outappears), but ant never printsBUILD SUCCESSFULand the shell never returns (Process.waitFor()on the parent side blocks forever; the serial agent must be interrupted).Root cause
VmProcessnever terminates.VmProcess.ProcessRunner.run()(core/src/core/org/jnode/vm/VmProcess.java:352-372) returns aftermainMethod.invoke(...)but never callsVmProcess.exit(...). Therunningflag staystrue, soProcess.waitFor()(same file, ~331-340) blocks indefinitely.VmProcessconstructor (~64-104) setsSystem.in/out/errif null but never assigns the instance fieldsin,out,err(declared ~55-59). SogetInputStream()/getErrorStream()/getOutputStream()return null, and ant'sStreamPumper(which wrapsproc.getInputStream()in a BufferedReader) throws the NPE above.Expected behavior
<java fork="true">should complete the process lifecycle: when the forkedmain()returns, the childVmProcessshould exit (running=false, exitValue=0, notify waiters) sowaitFor()returns and ant printsBUILD SUCCESSFUL/Total timeand control returns to the shell. Options for the streams: either wire the child'sSystem.out/errto in-memory pipes that the parent process reads (true stream capture), or at minimum return non-null streams soStreamPumperdoes not NPE.Environment
8c1f5362f+a9d541616, includes Flush System.out/err in DefaultCommandInvoker finally block #601)