ant-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bugzi...@apache.org
Subject DO NOT REPLY [Bug 47642] New: PumpStreamHandler can interleave I/O in incorrect order
Date Tue, 04 Aug 2009 20:48:32 GMT
https://issues.apache.org/bugzilla/show_bug.cgi?id=47642

           Summary: PumpStreamHandler can interleave I/O in incorrect
                    order
           Product: Ant
           Version: 1.7.1
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Core tasks
        AssignedTo: notifications@ant.apache.org
        ReportedBy: jglick@netbeans.org


--- Comment #0 from Jesse Glick <jglick@netbeans.org> 2009-08-04 13:48:30 PDT ---
Consider


<project default="run">
    <available property="compiled" file="Test.class"/>
    <target name="compile" unless="compiled">
        <echo file="Test.java">
public class Test {
    public static void main(String[] args) {
        System.out.println("out");
        System.out.flush();
        System.err.println("err");
    }
}
        </echo>
        <javac srcdir="." destdir="." includeantruntime="false" source="1.5"
includes="Test.java"/>
    </target>
    <target name="run" depends="compile">
        <java fork="true" classname="Test" classpath="."/>
    </target>
</project>


You would expect this program to always print "out" followed by "err", and when
run without Ant it does. When run using Ant, occasionally it prints "err"
followed by "out". This can be made frequent enough to observe by introducing
some artificial latency:


Index: src/main/org/apache/tools/ant/taskdefs/StreamPumper.java
===================================================================
--- src/main/org/apache/tools/ant/taskdefs/StreamPumper.java    (revision
799653)
+++ src/main/org/apache/tools/ant/taskdefs/StreamPumper.java    (working copy)
@@ -20,6 +20,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Random;
 import org.apache.tools.ant.util.FileUtils;

 /**
@@ -115,6 +116,11 @@
         synchronized (this) {
             started = true;
         }
+        if (new Random().nextBoolean()) {
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException ex) {}
+        }
         finished = false;
         finish = false;


The trouble is that PumpStreamHandler spawns one copier thread per I/O stream,
and there is no guarantee that these threads will not be preempted. "out\n"
becomes available on process.inputStream just before "err\n" becomes available
on process.errorStream, so only if the stdout StreamPumper is ready to run will
it actually run before the stderr StreamPumper. In other words, there is a race
condition.

As for a possible fix, java.nio.channels.Selector should be able to poll all
the process I/O streams deterministically. You would still need a separate
copier thread, but at least select() should return 1 after out.flush() was
called, and selectedKeys() should have stdout only, so the next call to
select() would happen only after stdout was processed. At least I think so.


Original report: http://www.netbeans.org/nonav/issues/show_bug.cgi?id=145980

-- 
Configure bugmail: https://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.

Mime
View raw message