Hello Brett et al.,

Please find attached a patch for apache commons exec with respect to two issues 
(note that I have only tested them under M$ Windows yet, but I am very 
confident that these changes should work under *nix too):

---

(1) ExecuteWatchdog test cases (DefaultExecutorTest.java): one for synchronous 
and one for asynchronous execution including the required test scripts 
(watchdog.bat, watchdog.sh) and test app (JavaApp.java). Whereas the one for 
asynchronous is a bit more elaborated and kind of "more correct", please note 
the hint on the well-known Java "bug"/issue under M$ Windows with respect to 
the Process.destroy() method in the asynchronous test case code.

---

(2) Add a method to CommandLine (CommandLine.java) to add arguments without 
quoting, i.e. pre-quoted arguments, because default quoting may not be correct 
in all cases. Note that I have not tried to find out if the default quoting can 
be changed accordingly. And also that maybe this problem is only M$ Windows 
specific, but I don't know (yet). The encountered problem was: 

I want to start an executable (runMemorySud.cmd) with a list of JVM GC options 
that in turn will then start a Java application utilising these JVM GC options. 
I failed to find an accepted way of specifying the following:

runMemorySud.cmd -XX:+UseParallelGC -XX:ParallelGCThreads=2

After quite some time I found out that the default quoting of apache commons 
exec is causing the problem, and with default pure standard Java it works as 
expected by using (see attached ProcessTest.java example):

Process p = new ProcessBuilder("runMemorySud.cmd", "10", "30", 
"-XX:+UseParallelGC", "\"-XX:ParallelGCThreads=2\"").start();

However, as I said, I found no way of being able to "propagate this to the 
ProcessBuilder through apache commons exec". Thus, the need for adding a 
so-called pre-quoted argument addArgument() method.

---

Would you mind applying these patches?

Thanks,
        Reinhold

P.S.: Please CC me in your potential responses as I am not subscribed to this 
mailing list.

___________________________________________________________
DI(FH) Reinhold Füreder, MPhil
Performance and Automated Test Engineer
dynaTrace software GmbH
Freistädter Str. 313, 4040 Linz, Austria
E [EMAIL PROTECTED]
T +43 (732) 246870.16. F +43 (732) 908176
>> Go beyond Monitoring, Take Action >> www.dynatrace.com
 
This e-mail message, including any attachments, is confidential and may contain 
legally privileged information. This message is intended solely for the use of 
the addressee. Use by others is prohibited. Disclosure, copying and 
distribution of this information to third parties is not permitted. If you have 
received this message in error, please notify us immediately and delete it from 
your system. The integrity and security of this message cannot be guaranteed 
and it may be subject to data corruption, interception and unauthorized 
amendment, for which we accept no liability.

Index: 
C:/data/jloadtrace/JakartaCommonsExec/src/test/java/org/apache/commons/exec/JavaApp.java
===================================================================
--- 
C:/data/jloadtrace/JakartaCommonsExec/src/test/java/org/apache/commons/exec/JavaApp.java
    (revision 0)
+++ 
C:/data/jloadtrace/JakartaCommonsExec/src/test/java/org/apache/commons/exec/JavaApp.java
    (revision 0)
@@ -0,0 +1,14 @@
+package org.apache.commons.exec;
+
+public class JavaApp {
+
+       public static void main(String[] args) {
+               System.out.println("JavaApp main()");
+               try {
+                       Thread.sleep(5000);
+               } catch (InterruptedException e) {
+                       e.printStackTrace();
+               }
+               System.out.println("JavaApp exit");
+       }
+}
Index: 
C:/data/jloadtrace/JakartaCommonsExec/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java
===================================================================
--- 
C:/data/jloadtrace/JakartaCommonsExec/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java
        (revision 518598)
+++ 
C:/data/jloadtrace/JakartaCommonsExec/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java
        (working copy)
@@ -33,7 +33,8 @@
     private ByteArrayOutputStream baos;
     private File testScript = TestUtil.resolveScriptForOS(testDir + "/test");
     private File errorTestScript = TestUtil.resolveScriptForOS(testDir + 
"/error");
-
+       private File watchdogTestScript = TestUtil.resolveScriptForOS(testDir + 
"/watchdog");
+       
     protected void setUp() throws Exception {
         baos = new ByteArrayOutputStream();
         exec.setStreamHandler(new PumpStreamHandler(baos, baos));
@@ -107,9 +108,70 @@
         assertTrue(handler.getException() instanceof ExecuteException);
         assertEquals("FOO..", baos.toString().trim());
     }
-    
-    
 
+       public void testWatchdog() throws Exception {
+               CommandLine cl = new CommandLine(watchdogTestScript);
+
+               ExecuteWatchdog watchDog = new ExecuteWatchdog(1000L);
+               exec.setWatchdog(watchDog);
+               try {
+                       exec.execute(cl);
+                       //System.out.println(baos.toString());                  
+                       fail("Must throw ExecuteException");
+               } catch (ExecuteException e) {
+                       //TODO: check return code M$ Windows vs. *nix
+                       assertEquals(1, e.getExitValue());
+               }
+               // Somehow the exception
+               assertEquals(false, watchDog.isWatching());
+               assertEquals(true, watchDog.killedProcess());
+       }
+
+    public void testExecuteAsyncWatchdog() throws Exception {
+       // Under M$ Windows killing processes via Process.destroy() does only
+       // work for directly executed processes, and not the possible child
+       // processes indirectly started from within the directly started
+       // script.
+       // What is happening is that the Process.waitFor() seemingly waits for
+       // the finishing of the whole child process tree (that is not killed
+       // by Process.destroy()).
+       // Thus, in order to use the ExecuteWatchdog for otherwise infinite
+       // running applications, the applications must be started directly!
+       // Cf. http://bugs.sun.com/bugdatabase/view_bug.do;:YfiG?bug_id=4770092
+       // Cf. 
http://www.velocityreviews.com/forums/t136443-processdestroy-on-win32.html
+       
+       // When we execute this test via Ant (or Eclipse) we know the required
+       // java executable location, as there must be a properly configured
+       // JAVA_HOME environment variable:
+               CommandLine cl = new 
CommandLine(System.getProperty("java.home") + "/bin/java");
+               // Set classpath to include JavaApp class - pure Java 
application - for 
+               // Ant (as well as Eclipse) build:
+               cl.addArguments("-cp bin;target/test-classes 
org.apache.commons.exec.JavaApp");
+
+               MockExecuteResultHandler handler = new 
MockExecuteResultHandler();
+        
+               ExecuteWatchdog watchDog = new ExecuteWatchdog(1000L);
+               exec.setWatchdog(watchDog);
+               try {
+                       exec.execute(cl, handler); // Note: JavaApp sleeps for 
5 sec
+                       // Sleep here (a) much longer than execute watchdog 
allows (1 sec),
+                       // and (b) also longer than normal JavaApp execution 
would last to
+                       // provoke execute watchdog action and be sure that the
+                       // Process.waitFor() really returns before the full 
JavaApp
+                       // sleeping time period of 5 sec:
+                       Thread.sleep(10000);
+               } catch (ExecuteException e) {
+                       fail("Caught ExecuteException: " + e);
+               }
+               //System.out.println(baos.toString());
+               assertEquals(false, watchDog.isWatching());
+               assertEquals(true, watchDog.killedProcess());
+        
+               //TODO: check return code M$ Windows vs. *nix
+        assertEquals(1, handler.getExitValue());
+        assertTrue(handler.getException() instanceof ExecuteException);
+    }
+
     protected void tearDown() throws Exception {
         baos.close();
     }
Index: C:/data/jloadtrace/JakartaCommonsExec/src/test/scripts/watchdog.bat
===================================================================
--- C:/data/jloadtrace/JakartaCommonsExec/src/test/scripts/watchdog.bat 
(revision 0)
+++ C:/data/jloadtrace/JakartaCommonsExec/src/test/scripts/watchdog.bat 
(revision 0)
@@ -0,0 +1,11 @@
[EMAIL PROTECTED] off
+
+REM This watchdog test script will just wait for some time to provoke killing 
this process by the watchdog
+
+REM Simulate sleep in Windows command shell scripts: cf. 
http://malektips.com/dos0017.html
[EMAIL PROTECTED] 127.0.0.1 -n 5 -w 1000 > nul
+
+REM This does not work interestingly
+REM PAUSE
+
+EXIT 0
\ No newline at end of file
Index: C:/data/jloadtrace/JakartaCommonsExec/src/test/scripts/watchdog.sh
===================================================================
--- C:/data/jloadtrace/JakartaCommonsExec/src/test/scripts/watchdog.sh  
(revision 0)
+++ C:/data/jloadtrace/JakartaCommonsExec/src/test/scripts/watchdog.sh  
(revision 0)
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+# This watchdog test script will just wait for user input to provoke killing 
this process by the watchdog
+
+sleep 5s
Index: 
C:/data/jloadtrace/JakartaCommonsExec/src/main/java/org/apache/commons/exec/CommandLine.java
===================================================================
--- 
C:/data/jloadtrace/JakartaCommonsExec/src/main/java/org/apache/commons/exec/CommandLine.java
        (revision 518598)
+++ 
C:/data/jloadtrace/JakartaCommonsExec/src/main/java/org/apache/commons/exec/CommandLine.java
        (working copy)
@@ -152,6 +152,18 @@
     }
 
     /**
+     * Add a single argument without handling quoting, i.e. assumes the user is
+     * pre-quoting herself if necessary.
+     * @param argument The argument to add
+     */
+    public void addArgumentWithoutQuoting(final String argument) {
+        if (argument == null)
+            return;
+
+        arguments.add(argument);
+    }
+    
+    /**
      * Returns the quoted arguments 
      * @return The quoted arguments
      */
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to