From af1ebdaf7f5659ca7c8b670eafcaadf50a515f0b Mon Sep 17 00:00:00 2001 From: Tim Whittington Date: Mon, 12 Aug 2013 21:45:44 +1200 Subject: [PATCH] Signal StreamPumper to finish before joining on it, otherwise all execs incur JOIN_TIMEOUT overhead. Drain available data in StreamPumper on finish, to allow output from fast executing tasks to be captured. Fixes https://issues.apache.org/bugzilla/show_bug.cgi?id=54128 Also avoid race where StreamPumper is stopped (e.g. after process exit) before thread running StreamPumper has entered the run() method. --- .../apache/tools/ant/taskdefs/PumpStreamHandler.java | 2 +- .../org/apache/tools/ant/taskdefs/StreamPumper.java | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/main/org/apache/tools/ant/taskdefs/PumpStreamHandler.java b/src/main/org/apache/tools/ant/taskdefs/PumpStreamHandler.java index 2ccae1e..42ba0f4 100644 --- a/src/main/org/apache/tools/ant/taskdefs/PumpStreamHandler.java +++ b/src/main/org/apache/tools/ant/taskdefs/PumpStreamHandler.java @@ -185,10 +185,10 @@ public class PumpStreamHandler implements ExecuteStreamHandler { return; } - t.join(JOIN_TIMEOUT); if (s != null && !s.isFinished()) { s.stop(); } + t.join(JOIN_TIMEOUT); while ((s == null || !s.isFinished()) && t.isAlive()) { t.interrupt(); t.join(JOIN_TIMEOUT); diff --git a/src/main/org/apache/tools/ant/taskdefs/StreamPumper.java b/src/main/org/apache/tools/ant/taskdefs/StreamPumper.java index c4ad991..b47e47b 100644 --- a/src/main/org/apache/tools/ant/taskdefs/StreamPumper.java +++ b/src/main/org/apache/tools/ant/taskdefs/StreamPumper.java @@ -116,7 +116,6 @@ public class StreamPumper implements Runnable { started = true; } finished = false; - finish = false; final byte[] buf = new byte[bufferSize]; @@ -130,13 +129,29 @@ public class StreamPumper implements Runnable { } length = is.read(buf); - if (length <= 0 || finish || Thread.interrupted()) { + if (length <= 0 || Thread.interrupted()) { break; } os.write(buf, 0, length); if (autoflush) { os.flush(); } + if (finish) { + break; + } + } + // On completion, drain any available data (which might be the first data available for quick executions) + if (finish) { + while((length = is.available()) > 0) { + if (Thread.interrupted()) { + break; + } + length = is.read(buf, 0, Math.min(length, buf.length)); + if (length <= 0) { + break; + } + os.write(buf, 0, length); + } } os.flush(); } catch (InterruptedException ie) { @@ -150,6 +165,7 @@ public class StreamPumper implements Runnable { FileUtils.close(os); } finished = true; + finish = false; synchronized (this) { notifyAll(); } -- 1.8.2