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]