Reading Input and Error Streams Concurrently using BufferedReaders Hangs

input, java, runtime

Solution

https://bugs.java.com/bugdatabase/view_bug?bug_id=4090471

The solution I've always used is to create a separate thread to read one of the streams, join on the thread when the main thread finishes reading, and then waitFor the process.

Problem

First off let me apologize to the SO community for coming to you with something that ought to be so trivial. But I've been at this all day and I'm at the end of my rope. There is a section of my program that needs pull text from an input stream and an error stream from a process that is launched using Runtime.getrunTime().exec() and pass it through to standard input and output in an orderly manner. I have a function that near as I can tell should work. But it seems to be getting caught in a catch-22 where it's waiting for the stream to report ready - but the stream has finished and is not reporting. I'm baffled. I can't think of another way to do this that fits my constraints and I'm rather skeptical that such a catch-22 can exist. Here is my code: ``` private void forwardStreamtoStd(InputStream in, InputStream err) throws IOException { int c = -1; BufferedReader inReader = new BufferedReader( new InputStreamReader(in, "US-ASCII")); BufferedReader errReader = new BufferedReader( new InputStreamReader(err, "US-ASCII")); boolean inFinished = false, errFinished = false; try { System.out.println("Begin stream read loop..."); while (!inFinished && !errFinished) { if (!inFinished) { while (inReader.ready()) { if ((c = inReader.read()) == -1) { inFinished = true; } else { System.out.print((char) c); } } } if (!errFinished) { while (errReader.ready()) { if ((c = errReader.read()) == -1) { errFinished = true; } else { System.err.print((char) c); } } } } System.out.println("End stream read loop."); } catch (IOException e) { throw e; } finally { errReader.close(); inReader.close(); } } ``` The problem seems to be that the reading loops are waiting for the streams to report ready, and as a result aren't seeing the -1 returned by read telling them that it's time to quit. I'm trying to avoid having either stream blocking, so that I can pull from both in turn when they are prepared. However, how can I catch the process's end of stream? Am I missing something? Shouldn't read report that it's read when it has an end of stream -1? The processes are finishing, and so their streams should be dying. What am I doing wrong here?

Original source