Details
-
Bug
-
Status: Resolved
-
Minor
-
Resolution: Fixed
-
1.1
-
None
-
RHEL 5, Ubuntu 10.04
Description
java.io.IOException: Write end dead at java.io.PipedInputStream.read(PipedInputStream.java:294) at com.mycompany.commonsexecrunner.App.main(App.java:48)
I came across this issue when I was trying to capture stdout with a PipedOutputStream and then pass that to a PipedInputStream. The following code will produce the error. The reason for the error is the PipedOutputStream is not being closed correctly, causing the PipedInputStream to break.
public static void main(String[] args) { System.out.println("Hello world"); CommandLine cl = CommandLine.parse("/bin/ls"); cl.addArgument("/opt"); DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler(); PipedOutputStream stdout = new PipedOutputStream(); PumpStreamHandler psh = new PumpStreamHandler(stdout); Executor exec = new DefaultExecutor(); exec.setStreamHandler(psh); try { System.out.println("Preparing to execute process - commandLine=" + cl.toString()); exec.execute(cl, handler); System.out.println("Process spun off successfully - process=" + cl.getExecutable()); } catch (ExecuteException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } PipedInputStream pis = null; try { pis = new PipedInputStream(stdout); } catch (IOException ex) { ex.printStackTrace(); } int x; try { while ((x = pis.read()) >= 0) { System.out.println("pis.available() " + pis.available()); System.out.println("x " + x); } } catch (IOException ex) { ex.printStackTrace(); } finally { try { pis.close(); } catch (IOException ex) { } } System.out.println("Goodbye world"); }
I was able to mitigate the error by modifying the createProcessOutputPump() method in the PumpStreamHandler class to accept the boolean value closeWhenExhausted, like was used for the setProcessInputStream() method.
protected void createProcessOutputPump(final InputStream is, final OutputStream os, final boolean closeWhenExhausted) { outputThread = createPump(is, os, closeWhenExhausted); }
This solution isn't implemented in the best way because in the end you have to pass a boolean value all the way down and it's kind of messy, but its a start.