commons-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Martin Sandiford (Created) (JIRA)" <j...@apache.org>
Subject [jira] [Created] (EXEC-63) Race condition in DefaultExecutor#execute(cmd, handler)
Date Thu, 23 Feb 2012 00:21:48 GMT
Race condition in DefaultExecutor#execute(cmd, handler)
-------------------------------------------------------

                 Key: EXEC-63
                 URL: https://issues.apache.org/jira/browse/EXEC-63
             Project: Commons Exec
          Issue Type: Bug
    Affects Versions: 1.1
         Environment: Windows 7/64 bit, JDK 1.6.0_27
            Reporter: Martin Sandiford


DefaultExecutor#execute(CommandLine, ExecuteResultHandler) can, and usually does, return before
the target process has actually started.  This can result in a race condition where several
asynchronous processes are coupled by PipedInputStream/PipedOutputStream objects.

The following example shows the issue:

import java.io.*;
import org.apache.commons.exec.*;

public class Borken {
  public static int pipe(OutputStream out, OutputStream err, InputStream in, CommandLine cmd0,
CommandLine cmd1)
      throws IOException {
    PipedInputStream pipeIn = new PipedInputStream();
    PipedOutputStream pipeOut = new PipedOutputStream(pipeIn);
    DefaultExecutor exec0 = new DefaultExecutor();
    exec0.setStreamHandler(new PumpStreamHandler(pipeOut, null, in));
    exec0.execute(cmd0, new DefaultExecuteResultHandler());
    
    // If the following line is commented, deadlock occurs
    //try { Thread.sleep(100); } catch (InterruptedException e) { }

    DefaultExecutor exec1 = new DefaultExecutor();
    exec1.setStreamHandler(new PumpStreamHandler(out, err, pipeIn));
    return exec1.execute(cmd1);
  }
  
  public static void main(String... args) {
    CommandLine cmd0 = new CommandLine("cmd").addArgument("/c").addArgument("dir");
    //CommandLine cmd0 = new CommandLine("ls").addArgument("-l");
    CommandLine cmd1 = new CommandLine("sort");
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ByteArrayOutputStream err = new ByteArrayOutputStream();
    ByteArrayInputStream in = new ByteArrayInputStream(new byte[0]);
    try {
      int result = pipe(out, err, in, cmd0, cmd1);
      System.out.format("Result code: %d%n", result);
      System.out.format("Out: %s%n", out.toString());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

One possible solution is to pass in a semaphore object into DefaultExecutor#executeInternal
which is notified once the process is started.  The execute(CommandLine, Map, ExecuteResultHandler)
method can then wait on this before returning.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Mime
View raw message