Uploaded image for project: 'Commons Exec'
  1. Commons Exec
  2. EXEC-49

"Write dead end" IOException when using Piped streams w/PumpStreamHandler

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Minor
    • Resolution: Fixed
    • 1.1
    • 1.2
    • None
    • RHEL 5, Ubuntu 10.04

    Description

      Sad Trombone
      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.

      Throws IOException
          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.

      Attachments

        1. exec-49.patch
          7 kB
          Siegfried Goeschl

        Activity

          People

            sgoeschl Siegfried Goeschl
            kevintelford Kevin Telford
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Time Tracking

                Estimated:
                Original Estimate - 4h
                4h
                Remaining:
                Remaining Estimate - 4h
                4h
                Logged:
                Time Spent - Not Specified
                Not Specified