From ccfd2df5248f621f43923c7b21499a3d0d87c90f Mon Sep 17 00:00:00 2001 From: darius42 Date: Thu, 10 Jul 2008 22:49:47 +0000 Subject: Fix for bug 2015469 - Modified CaptureStreamHandler so that it spawns threads to read from stdout and stderr simultaneously. This should prevent deadlocks if no data is available on stderr, but stdout has filled it's buffer. git-svn-id: file:///home/sven/projects/JOGL/temp/ant-contrib/svn/ant-contrib-code/cpptasks/trunk@172 32d7a393-a5a9-423c-abd3-5d954feb1f2f --- .../java/net/sf/antcontrib/cpptasks/CUtil.java | 2 +- .../cpptasks/compiler/CaptureStreamHandler.java | 94 ++++++++++++++-------- .../antcontrib/cpptasks/compiler/LineReader.java | 66 +++++++++++++++ 3 files changed, 129 insertions(+), 33 deletions(-) create mode 100644 src/main/java/net/sf/antcontrib/cpptasks/compiler/LineReader.java (limited to 'src/main') diff --git a/src/main/java/net/sf/antcontrib/cpptasks/CUtil.java b/src/main/java/net/sf/antcontrib/cpptasks/CUtil.java index 482593e..29e9d22 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/CUtil.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/CUtil.java @@ -367,7 +367,7 @@ public class CUtil { } } /** - * Compares the contents of 2 arrays for equaliy. + * Compares the contents of 2 arrays for equality. */ public static boolean sameList(Object[] a, Object[] b) { if (a == null || b == null || a.length != b.length) { diff --git a/src/main/java/net/sf/antcontrib/cpptasks/compiler/CaptureStreamHandler.java b/src/main/java/net/sf/antcontrib/cpptasks/compiler/CaptureStreamHandler.java index 83c59f7..0317289 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/compiler/CaptureStreamHandler.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/compiler/CaptureStreamHandler.java @@ -15,15 +15,14 @@ * limitations under the License. */ package net.sf.antcontrib.cpptasks.compiler; -import java.io.BufferedReader; + import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.OutputStream; -import java.util.Vector; import org.apache.tools.ant.taskdefs.Execute; import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; + /** * Implements ExecuteStreamHandler to capture the output of a Execute to an * array of strings @@ -43,52 +42,41 @@ public class CaptureStreamHandler implements ExecuteStreamHandler { Execute exec = new Execute(handler); exec.setCommandline(cmdline); try { - int status = exec.execute(); + exec.execute(); } catch (IOException ex) { } return handler.getOutput(); } + private InputStream errorStream; private InputStream fromProcess; + private String[] output; + private LineReader outputReader; + private LineReader errorReader; + private Thread outputReaderThread; + private Thread errorReaderThread; + public CaptureStreamHandler() { } + public String[] getOutput() { - String[] output; - if (fromProcess != null) { - Vector lines = new Vector(10); - try { - BufferedReader reader = new BufferedReader( - new InputStreamReader(errorStream)); - for (int i = 0; i < 2; i++) { - for (int j = 0; j < 100; j++) { - String line = reader.readLine(); - if (line == null) { - reader = new BufferedReader(new InputStreamReader( - fromProcess)); - break; - } - lines.addElement(line); - } - } - } catch (IOException ex) { - } - output = new String[lines.size()]; - lines.copyInto(output); - return output; + if (this.output != null) { + return this.output; + } else { + return new String[0]; } - output = new String[0]; - return output; } + /** * Install a handler for the error stream of the subprocess. * * @param is - * input stream to read from the error stream from the - * subprocess + * input stream to read from the error stream from the subprocess */ public void setProcessErrorStream(InputStream is) throws IOException { errorStream = is; } + /** * Install a handler for the input stream of the subprocess. * @@ -99,24 +87,66 @@ public class CaptureStreamHandler implements ExecuteStreamHandler { public void setProcessInputStream(OutputStream os) throws IOException { os.close(); } + /** * Install a handler for the output stream of the subprocess. * * @param is - * input stream to read from the error stream from the - * subprocess + * input stream to read from the error stream from the subprocess */ public void setProcessOutputStream(InputStream is) throws IOException { fromProcess = is; } + /** * Start handling of the streams. */ public void start() throws IOException { + this.outputReader = new LineReader(this.fromProcess); + this.errorReader = new LineReader(this.errorStream); + this.outputReaderThread = new Thread(this.outputReader); + this.errorReaderThread = new Thread(this.errorReader); + + outputReaderThread.start(); + errorReaderThread.start(); } + /** * Stop handling of the streams - will not be restarted. */ public void stop() { + try { + if (this.outputReaderThread != null) { + this.outputReaderThread.join(); + } + if (this.errorReaderThread != null) { + this.errorReaderThread.join(); + } + } catch (InterruptedException e) { + } + + String[] outputLines = null; + String[] errorLines = null; + + if (this.outputReader != null) { + outputLines = this.outputReader.getLines(); + } else { + outputLines = new String[0]; + } + + if (this.errorReader != null) { + errorLines = this.errorReader.getLines(); + } else { + errorLines = new String[0]; + } + + this.output = new String[outputLines.length + errorLines.length]; + int pos = 0; + for (int i = 0; i < errorLines.length; i++) { + this.output[pos++] = errorLines[i]; + } + for (int i = 0; i < outputLines.length; i++) { + this.output[pos++] = outputLines[i]; + } } } diff --git a/src/main/java/net/sf/antcontrib/cpptasks/compiler/LineReader.java b/src/main/java/net/sf/antcontrib/cpptasks/compiler/LineReader.java new file mode 100644 index 0000000..b43d3ae --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/compiler/LineReader.java @@ -0,0 +1,66 @@ +/* + * + * Copyright 2008 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Vector; + +/** + * Reads an array of lines from the provided input stream. + */ +public class LineReader implements Runnable { + + private InputStream is; + private String[] lines; + + /** + * Create a new line reader. + * + * @param is + * input stream to read data from + */ + public LineReader(InputStream is) { + this.is = is; + } + + public String[] getLines() { + return this.lines; + } + + /** + * Copies data from the input stream to the output String[]. + */ + public void run() { + try { + BufferedReader reader = new BufferedReader(new InputStreamReader( + this.is)); + + Vector lines = new Vector(10); + String line = null; + while ((line = reader.readLine()) != null) { + lines.addElement(line); + } + + this.lines = new String[lines.size()]; + lines.copyInto(this.lines); + } catch (IOException e) { + } + } +} -- cgit v1.2.3