commons-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Martin Sandiford (Commented) (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (EXEC-63) Race condition in DefaultExecutor#execute(cmd, handler)
Date Tue, 28 Feb 2012 01:25:49 GMT

    [ https://issues.apache.org/jira/browse/EXEC-63?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13217795#comment-13217795
] 

Martin Sandiford commented on EXEC-63:
--------------------------------------

Patch for test case from https://github.com/msandiford/commons-exec commit 4c2f449dd5605975d38a2c686dec3c00b7414eee

{code:title=test-case.diff|borderStyle=solid}
--- a/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java
+++ b/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java
@@ -1094,6 +1094,49 @@ public class DefaultExecutorTest extends TestCase {
         assertTrue("Not a single process was killed by the watch dog", watchdogKilledProcessCounter
> 0);
     }

+
+    /**
+     * Test EXEC-63 (https://issues.apache.org/jira/browse/EXEC-63).
+     *
+     * Frequent deadlock when constructing a command pipe chain.
+     * Please note that a successful test is no proof that the issues was fixed.
+     *
+     * @throws IOException the test failed
+     */
+    public void testExec_63() throws IOException {
+        CommandLine cmd0;
+        CommandLine cmd1;
+        if (OS.isFamilyUnix()) {
+            cmd0 = new CommandLine("ls").addArgument("-l");
+            cmd1 = new CommandLine("sort");
+        } else if (OS.isFamilyWindows()) {
+            cmd0 = new CommandLine("cmd").addArgument("/c").addArgument("dir");
+            cmd1 = new CommandLine("sort");
+        } else {
+            System.err.println("The test 'testExec_63' does not support the following OS
: " + System.getProperty("os.name"));
+            return;
+        }
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        ByteArrayOutputStream err = new ByteArrayOutputStream();
+        ByteArrayInputStream in = new ByteArrayInputStream(new byte[0]);
+        PipedInputStream pipeIn = new PipedInputStream();
+        PipedOutputStream pipeOut = new PipedOutputStream(pipeIn);
+        DefaultExecutor exec0 = new DefaultExecutor();
+        ExecuteWatchdog watchdog0 = new ExecuteWatchdog(5000);
+        exec0.setWatchdog(watchdog0);
+        exec0.setStreamHandler(new PumpStreamHandler(pipeOut, null, in));
+        exec0.execute(cmd0, new DefaultExecuteResultHandler());
+
+        DefaultExecutor exec1 = new DefaultExecutor();
+        ExecuteWatchdog watchdog1 = new ExecuteWatchdog(5000);
+        exec1.setWatchdog(watchdog1);
+        exec1.setStreamHandler(new PumpStreamHandler(out, err, pipeIn));
+        int result = exec1.execute(cmd1);
+        assertTrue("Command exited with status 0", result == 0);
+        assertTrue("Output was as expected", out.toString().length() > 500);
+        assertEquals("No errors were output", err.toString().trim(), "");
+    }
+
     // ======================================================================
     // === Long running tests
     // ======================================================================
{code}

                
> 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
>   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 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