Return-Path: Delivered-To: apmail-jakarta-ant-dev-archive@apache.org Received: (qmail 62995 invoked from network); 5 Apr 2002 12:56:46 -0000 Received: from unknown (HELO nagoya.betaversion.org) (192.18.49.131) by daedalus.apache.org with SMTP; 5 Apr 2002 12:56:46 -0000 Received: (qmail 18774 invoked by uid 97); 5 Apr 2002 12:56:36 -0000 Delivered-To: qmlist-jakarta-archive-ant-dev@jakarta.apache.org Received: (qmail 18716 invoked by uid 97); 5 Apr 2002 12:56:36 -0000 Mailing-List: contact ant-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Subscribe: List-Help: List-Post: List-Id: "Ant Developers List" Reply-To: "Ant Developers List" Delivered-To: mailing list ant-dev@jakarta.apache.org Received: (qmail 18705 invoked by uid 97); 5 Apr 2002 12:56:35 -0000 Date: 5 Apr 2002 12:56:34 -0000 Message-ID: <20020405125634.82415.qmail@icarus.apache.org> From: bodewig@apache.org To: jakarta-ant-cvs@apache.org Subject: cvs commit: jakarta-ant/src/testcases/org/apache/tools/ant/taskdefs ExecuteJavaTest.java TimeProcess.java ExecuteWatchdogTest.java X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N bodewig 02/04/05 04:56:34 Modified: src/main/org/apache/tools/ant/taskdefs ExecTask.java ExecuteJava.java ExecuteWatchdog.java Java.java src/main/org/apache/tools/ant/util TimeoutObserver.java Watchdog.java src/testcases/org/apache/tools/ant/taskdefs ExecuteWatchdogTest.java Added: src/testcases/org/apache/tools/ant/taskdefs ExecuteJavaTest.java TimeProcess.java Log: timeout support for PR: 5299 Revision Changes Path 1.31 +3 -3 jakarta-ant/src/main/org/apache/tools/ant/taskdefs/ExecTask.java Index: ExecTask.java =================================================================== RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/ExecTask.java,v retrieving revision 1.30 retrieving revision 1.31 diff -u -r1.30 -r1.31 --- ExecTask.java 5 Apr 2002 09:28:54 -0000 1.30 +++ ExecTask.java 5 Apr 2002 12:56:34 -0000 1.31 @@ -88,7 +88,7 @@ private File dir; protected boolean failOnError = false; protected boolean newEnvironment = false; - private Integer timeout = null; + private Long timeout = null; private Environment env = new Environment(); protected Commandline cmdl = new Commandline(); private FileOutputStream fos = null; @@ -104,7 +104,7 @@ /** * Timeout in milliseconds after which the process will be killed. */ - public void setTimeout(Integer value) { + public void setTimeout(Long value) { timeout = value; } @@ -377,7 +377,7 @@ if (timeout == null) { return null; } - return new ExecuteWatchdog(timeout.intValue()); + return new ExecuteWatchdog(timeout.longValue()); } /** 1.19 +87 -15 jakarta-ant/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java Index: ExecuteJava.java =================================================================== RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java,v retrieving revision 1.18 retrieving revision 1.19 diff -u -r1.18 -r1.19 --- ExecuteJava.java 10 Jan 2002 13:59:31 -0000 1.18 +++ ExecuteJava.java 5 Apr 2002 12:56:34 -0000 1.19 @@ -1,7 +1,7 @@ /* * The Apache Software License, Version 1.1 * - * Copyright (c) 2000-2001 The Apache Software Foundation. All rights + * Copyright (c) 2000-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -62,21 +62,28 @@ import org.apache.tools.ant.types.Commandline; import org.apache.tools.ant.types.CommandlineJava; import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.util.TimeoutObserver; +import org.apache.tools.ant.util.Watchdog; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.io.PrintStream; -/* +/** * * @author thomas.haas@softwired-inc.com * @author Stefan Bodewig */ -public class ExecuteJava { +public class ExecuteJava implements Runnable, TimeoutObserver { private Commandline javaCommand = null; private Path classpath = null; private CommandlineJava.SysProperties sysProperties = null; + private Method main = null; + private Long timeout = null; + private Throwable caught = null; + private boolean timedOut = false; + private Thread thread = null; public void setJavaCommand(Commandline javaCommand) { this.javaCommand = javaCommand; @@ -99,9 +106,15 @@ public void setOutput(PrintStream out) { } + /** + * @since 1.19, Ant 1.5 + */ + public void setTimeout(Long timeout) { + this.timeout = timeout; + } + public void execute(Project project) throws BuildException{ final String classname = javaCommand.getExecutable(); - final Object[] argument = { javaCommand.getArguments() }; AntClassLoader loader = null; try { @@ -120,21 +133,41 @@ target = loader.forceLoadClass(classname); AntClassLoader.initializeClass(target); } - final Method main = target.getMethod("main", param); - main.invoke(null, argument); + main = target.getMethod("main", param); + + if (timeout == null) { + run(); + } else { + thread = new Thread(this, "ExecuteJava"); + Watchdog w = new Watchdog(timeout.longValue()); + w.addTimeoutObserver(this); + synchronized (this) { + thread.start(); + w.start(); + try { + wait(); + } catch (InterruptedException e) {} + if (timedOut) { + project.log("Timeout: killed the sub-process", + Project.MSG_WARN); + } else { + thread = null; + w.stop(); + } + } + } + + if (caught != null) { + throw caught; + } + } catch (NullPointerException e) { throw new BuildException("Could not find main() method in " + classname); } catch (ClassNotFoundException e) { throw new BuildException("Could not find " + classname + ". Make sure you have it in your classpath"); - } catch (InvocationTargetException e) { - Throwable t = e.getTargetException(); - if (!(t instanceof SecurityException)) { - throw new BuildException(t); - } - else { - throw (SecurityException)t; - } - } catch (Exception e) { + } catch (SecurityException e) { + throw e; + } catch (Throwable e) { throw new BuildException(e); } finally { if (loader != null) { @@ -145,5 +178,44 @@ sysProperties.restoreSystem(); } } + } + + /** + * @since 1.19, Ant 1.5 + */ + public void run() { + final Object[] argument = { javaCommand.getArguments() }; + try { + main.invoke(null, argument); + } catch (InvocationTargetException e) { + Throwable t = e.getTargetException(); + if (!(t instanceof InterruptedException)) { + caught = t; + } /* else { swallow, probably due to timeout } */ + } catch (Throwable t) { + caught = t; + } finally { + synchronized (this) { + notifyAll(); + } + } + } + + /** + * @since 1.19, Ant 1.5 + */ + public synchronized void timeoutOccured(Watchdog w) { + if (thread != null) { + timedOut = true; + thread.interrupt(); + } + notifyAll(); + } + + /** + * @since 1.19, Ant 1.5 + */ + public boolean killedProcess() { + return timedOut; } } 1.8 +1 -1 jakarta-ant/src/main/org/apache/tools/ant/taskdefs/ExecuteWatchdog.java Index: ExecuteWatchdog.java =================================================================== RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/ExecuteWatchdog.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- ExecuteWatchdog.java 5 Apr 2002 10:13:02 -0000 1.7 +++ ExecuteWatchdog.java 5 Apr 2002 12:56:34 -0000 1.8 @@ -98,7 +98,7 @@ * * @param timeout the timeout for the process in milliseconds. It must be greather than 0. */ - public ExecuteWatchdog(int timeout) { + public ExecuteWatchdog(long timeout) { watchdog = new Watchdog(timeout); watchdog.addTimeoutObserver(this); } 1.37 +32 -3 jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Java.java Index: Java.java =================================================================== RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Java.java,v retrieving revision 1.36 retrieving revision 1.37 diff -u -r1.36 -r1.37 --- Java.java 5 Apr 2002 09:28:54 -0000 1.36 +++ Java.java 5 Apr 2002 12:56:34 -0000 1.37 @@ -91,6 +91,7 @@ private PrintStream outStream = null; private boolean failOnError = false; private boolean append = false; + private Long timeout = null; /** * Do the execution. @@ -309,6 +310,15 @@ this.append = append; } + /** + * Timeout in milliseconds after which the process will be killed. + * + * @since 1.37, Ant 1.5 + */ + public void setTimeout(Long value) { + timeout = value; + } + protected void handleOutput(String line) { if (outStream != null) { outStream.println(line); @@ -336,6 +346,7 @@ exe.setJavaCommand(command.getJavaCommand()); exe.setClasspath(command.getClasspath()); exe.setSystemProperties(command.getSystemProperties()); + exe.setTimeout(timeout); if (out != null) { try { outStream = @@ -366,10 +377,11 @@ if (out == null) { exe = new Execute(new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN), - null); + createWatchdog()); } else { fos = new FileOutputStream(out.getAbsolutePath(), append); - exe = new Execute(new PumpStreamHandler(fos), null); + exe = new Execute(new PumpStreamHandler(fos), + createWatchdog()); } exe.setAntRun(project); @@ -395,7 +407,11 @@ exe.setCommandline(command); try { - return exe.execute(); + int rc = exe.execute(); + if(exe.killedProcess()) { + log("Timeout: killed the sub-process",Project.MSG_WARN); + } + return rc; } catch (IOException e) { throw new BuildException(e, location); } @@ -427,4 +443,17 @@ public void clearArgs() { cmdl.clearJavaArgs(); } + + /** + * Create the Watchdog to kill a runaway process. + * + * @since 1.37, Ant 1.5 + */ + protected ExecuteWatchdog createWatchdog() throws BuildException { + if (timeout == null) { + return null; + } + return new ExecuteWatchdog(timeout.longValue()); + } + } 1.2 +1 -1 jakarta-ant/src/main/org/apache/tools/ant/util/TimeoutObserver.java Index: TimeoutObserver.java =================================================================== RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/util/TimeoutObserver.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- TimeoutObserver.java 5 Apr 2002 10:13:02 -0000 1.1 +++ TimeoutObserver.java 5 Apr 2002 12:56:34 -0000 1.2 @@ -57,7 +57,7 @@ /** * Interface for classes that want to be notified by Watchdog. * - * @since 1.5 + * @since Ant 1.5 * * @see org.apache.tools.ant.util.Watchdog * 1.2 +1 -1 jakarta-ant/src/main/org/apache/tools/ant/util/Watchdog.java Index: Watchdog.java =================================================================== RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/util/Watchdog.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- Watchdog.java 5 Apr 2002 10:13:02 -0000 1.1 +++ Watchdog.java 5 Apr 2002 12:56:34 -0000 1.2 @@ -113,7 +113,7 @@ long now; while (!stopped && until > (now = System.currentTimeMillis())) { try { - wait(until - now); + wait(until - now); } catch (InterruptedException e) {} } if (!stopped) { 1.10 +7 -17 jakarta-ant/src/testcases/org/apache/tools/ant/taskdefs/ExecuteWatchdogTest.java Index: ExecuteWatchdogTest.java =================================================================== RCS file: /home/cvs/jakarta-ant/src/testcases/org/apache/tools/ant/taskdefs/ExecuteWatchdogTest.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- ExecuteWatchdogTest.java 4 Mar 2002 08:49:35 -0000 1.9 +++ ExecuteWatchdogTest.java 5 Apr 2002 12:56:34 -0000 1.10 @@ -95,13 +95,13 @@ classpath = System.getProperty("java.class.path"); } - // JDK 1.1 needs classes.zip in -classpath argument - if (Project.getJavaVersion() == Project.JAVA_1_1) { - classpath += File.pathSeparator - + System.getProperty("java.home") - + File.separator + "lib" - + File.separator + "classes.zip"; - } + // JDK 1.1 needs classes.zip in -classpath argument + if (Project.getJavaVersion() == Project.JAVA_1_1) { + classpath += File.pathSeparator + + System.getProperty("java.home") + + File.separator + "lib" + + File.separator + "classes.zip"; + } return classpath; } @@ -196,15 +196,5 @@ // process should be dead and well finished assertEquals(0, process.exitValue()); assertTrue("process should not have been killed", !watchdog.killedProcess()); - } - - public static class TimeProcess { - public static void main(String[] args) throws Exception { - int time = Integer.parseInt(args[0]); - if (time < 1) { - throw new IllegalArgumentException("Invalid time: " + time); - } - Thread.sleep(time); - } } } 1.1 jakarta-ant/src/testcases/org/apache/tools/ant/taskdefs/ExecuteJavaTest.java Index: ExecuteJavaTest.java =================================================================== /* * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Ant", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ package org.apache.tools.ant.taskdefs; import org.apache.tools.ant.Project; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.Commandline; import java.io.File; import junit.framework.TestCase; /** * Simple testcase for the ExecuteJava class - mostly stolen from * ExecuteWatchdogTest. * * @author Stephane Bailliez * @author Stefan Bodewig */ public class ExecuteJavaTest extends TestCase { private final static int TIME_OUT = 5000; private final static int CLOCK_ERROR=200; private final static int TIME_OUT_TEST=TIME_OUT-CLOCK_ERROR; private ExecuteJava ej; private Project project; public ExecuteJavaTest(String name) { super(name); } protected void setUp(){ ej = new ExecuteJava(); ej.setTimeout(new Long(TIME_OUT)); project = new Project(); project.setBasedir("."); ej.setClasspath(new Path(project, getTestClassPath())); } private Commandline getCommandline(int timetorun) throws Exception { Commandline cmd = new Commandline(); cmd.setExecutable(TimeProcess.class.getName()); cmd.createArgument().setValue(String.valueOf(timetorun)); return cmd; } public void testNoTimeOut() throws Exception { Commandline cmd = getCommandline(TIME_OUT/2); ej.setJavaCommand(cmd); ej.execute(project); assertTrue("process should not have been killed", !ej.killedProcess()); } // test that the watchdog ends the process public void testTimeOut() throws Exception { Commandline cmd = getCommandline(TIME_OUT*2); ej.setJavaCommand(cmd); long now = System.currentTimeMillis(); ej.execute(project); long elapsed = System.currentTimeMillis() - now; assertTrue("process should have been killed", ej.killedProcess()); assertTrue("elapse time of "+elapsed +" ms is less than timeout value of "+TIME_OUT_TEST+" ms", elapsed >= TIME_OUT_TEST); assertTrue("elapse time of "+elapsed +" ms is greater than run value of "+(TIME_OUT*2)+" ms", elapsed < TIME_OUT*2); } /** * Dangerous method to obtain the classpath for the test. This is * severely tighted to the build.xml properties. */ private static String getTestClassPath(){ String classpath = System.getProperty("build.tests"); if (classpath == null) { System.err.println("WARNING: 'build.tests' property is not available !"); classpath = System.getProperty("java.class.path"); } // JDK 1.1 needs classes.zip in -classpath argument if (Project.getJavaVersion() == Project.JAVA_1_1) { classpath += File.pathSeparator + System.getProperty("java.home") + File.separator + "lib" + File.separator + "classes.zip"; } return classpath; } } 1.1 jakarta-ant/src/testcases/org/apache/tools/ant/taskdefs/TimeProcess.java Index: TimeProcess.java =================================================================== /* * The Apache Software License, Version 1.1 * * Copyright (c) 2000-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Ant", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ package org.apache.tools.ant.taskdefs; /** * Helper class for ExecuteWatchdogTest and ExecuteJavaTest. * *

Used to be an inner class of ExecuteWatchdogTest. * * @author Stephane Bailliez */ public class TimeProcess { public static void main(String[] args) throws Exception { int time = Integer.parseInt(args[0]); if (time < 1) { throw new IllegalArgumentException("Invalid time: " + time); } Thread.sleep(time); } } -- To unsubscribe, e-mail: For additional commands, e-mail: