You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Martin Sandiford (JIRA)" <ji...@apache.org> on 2014/11/20 12:13:34 UTC
[jira] [Commented] (EXEC-63) Race condition in
DefaultExecutor#execute(cmd, handler)
[ https://issues.apache.org/jira/browse/EXEC-63?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14219257#comment-14219257 ]
Martin Sandiford commented on EXEC-63:
--------------------------------------
I think {{testExec_60()}} is a bit fragile, and highly dependent on an included ping script taking pretty much exactly the right amount of time.
Having a look at SVN trunk, it appears this test has been updated to retry more times (180 up from 20). This appears to fix the issue on the machines I have access to (MacOS 1.8.0-b132, Windows 7 1.7.0_25, Linux 1.7.0_72). The old test used to fail occasionally on MacOS and all the time on Windows 7.
There is a fix in the github repo that makes the test more reliable. This fix is similar to what has been applied to trunk.
https://github.com/msandiford/commons-exec/commit/8abb8352d0f5d3dfc64edafdd65fb76bd41ddbb8
> 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)