You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Michael Vorburger (JIRA)" <ji...@apache.org> on 2014/11/20 00:53:34 UTC

[jira] [Updated] (EXEC-63) Race condition in DefaultExecutor#execute(cmd, handler)

     [ https://issues.apache.org/jira/browse/EXEC-63?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Michael Vorburger updated EXEC-63:
----------------------------------
    Attachment: EXEC-63_DefaultExecutor.patch

Just in case this may help in moving forward with integrating this one, as I've noticed that commons-exec is still on SVN and not Git, I've created the attached via svn diff >EXEC-63_DefaultExecutor.patch of the change proposed above (manually retyped it, exact same thing; as I wanted to try this out applied on top of current latest commons-exec trunk). I'm too lazy to do the same for the other patch for new testExec_63() in DefaultExecutorTest.

It appears this proposed change breaks existing Exec60Test.testExec_60() line 86 ("Not a single process was killed by the watch dog") when applied as-is to current latest SVN rev 1640638. I have not investigated if this would be easy to fix, or is a sign of a real regression this patch would cause.. and how to improve this patch.. [~britter] perhaps you could look into this?

PS: I was trying out if this one fixes my https://github.com/vorburger/MariaDB4j/issues/10 issue (it does not, that's an unrelated problem).

> 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
>              Labels: deadlock
>         Attachments: EXEC-63_DefaultExecutor.patch
>
>   Original Estimate: 24h
>  Remaining Estimate: 24h
>
> {{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:
> {code:title=Borken.java|borderStyle=solid}
> 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();
>     }
>   }
> }
> {code}
> 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 was sent by Atlassian JIRA
(v6.3.4#6332)