Author: stevel Date: Tue Oct 17 12:28:20 2006 New Revision: 465013 URL: http://svn.apache.org/viewvc?view=rev&rev=465013 Log: Having learned about how the java memory model really works, I have had a quick code review of the threading here.
1. stuff that is shared read is always marked volatile, to avoid being compiled out. 2. added more synchronization when appropriate. I make no claims as to thread safety here, as I was never that good at formal proofs of correctness. Modified: ant/core/trunk/WHATSNEW ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/ExecuteWatchdog.java ant/core/trunk/src/main/org/apache/tools/ant/util/Watchdog.java Modified: ant/core/trunk/WHATSNEW URL: http://svn.apache.org/viewvc/ant/core/trunk/WHATSNEW?view=diff&rev=465013&r1=465012&r2=465013 ============================================================================== --- ant/core/trunk/WHATSNEW (original) +++ ant/core/trunk/WHATSNEW Tue Oct 17 12:28:20 2006 @@ -12,6 +12,10 @@ * Upgraded XML API and parser to Xerces 2.8.1 +* A code review of some threaded logic has tightened up the synchronization + of Watchdog, ExecuteWatchdog and ExecuteJava, which could reduce the occurence + of race conditions here, especially on Java1.5+. + Changes from Ant 1.7.0Beta2 to Ant 1.7.0Beta3 ============================================= @@ -24,6 +28,13 @@ the java class file. Bugzilla report 33604. * Defer reference process. Bugzilla 36955, 34458, 37688. + This may break build files in which a reference was set in a target which was + never executed. Historically, Ant would set the reference early on, during parse + time, so the datatype would be defined. Now it requires the reference to have + been in a bit of the build file which was actually executed. If you get + an error about an undefined reference, locate the reference and move it somewhere + where it is used, or fix the depends attribute of the target in question to + depend on the target which defines the reference/datatype. Fixed bugs: ----------- Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java?view=diff&rev=465013&r1=465012&r2=465013 ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/ExecuteJava.java Tue Oct 17 12:28:20 2006 @@ -50,8 +50,8 @@ private Permissions perm = null; private Method main = null; private Long timeout = null; - private Throwable caught = null; - private boolean timedOut = false; + private volatile Throwable caught = null; + private volatile boolean timedOut = false; private Thread thread = null; /** Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/ExecuteWatchdog.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/ExecuteWatchdog.java?view=diff&rev=465013&r1=465012&r2=465013 ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/ExecuteWatchdog.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/ExecuteWatchdog.java Tue Oct 17 12:28:20 2006 @@ -45,13 +45,13 @@ private Process process; /** say whether or not the watchdog is currently monitoring a process */ - private boolean watch = false; + private volatile boolean watch = false; /** exception that might be thrown during the process execution */ private Exception caught = null; /** say whether or not the process was killed due to running overtime */ - private boolean killedProcess = false; + private volatile boolean killedProcess = false; /** will tell us whether timeout has occurred */ private Watchdog watchdog; @@ -103,15 +103,15 @@ */ public synchronized void stop() { watchdog.stop(); - watch = false; - process = null; + cleanUp(); } /** * Called after watchdog has finished. + * This can be called in the watchdog thread * @param w the watchdog */ - public void timeoutOccured(Watchdog w) { + public synchronized void timeoutOccured(Watchdog w) { try { try { // We must check if the process was not stopped @@ -135,7 +135,7 @@ /** * reset the monitor flag and the process. */ - protected void cleanUp() { + protected synchronized void cleanUp() { watch = false; process = null; } @@ -148,7 +148,7 @@ * @throws BuildException a wrapped exception over the one that was * silently swallowed and stored during the process run. */ - public void checkException() throws BuildException { + public synchronized void checkException() throws BuildException { if (caught != null) { throw new BuildException("Exception in ExecuteWatchdog.run: " + caught.getMessage(), caught); Modified: ant/core/trunk/src/main/org/apache/tools/ant/util/Watchdog.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/util/Watchdog.java?view=diff&rev=465013&r1=465012&r2=465013 ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/util/Watchdog.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/util/Watchdog.java Tue Oct 17 12:28:20 2006 @@ -33,7 +33,16 @@ private Vector observers = new Vector(1); private long timeout = -1; - private boolean stopped = false; + /** + * marked as volatile to stop the compiler caching values or (in java1.5+, + * reordering access) + */ + private volatile boolean stopped = false; + /** + * Error string. + * [EMAIL PROTECTED] + */ + public static final String ERROR_INVALID_TIMEOUT = "timeout less than 1."; /** * Constructor for Watchdog. @@ -41,7 +50,7 @@ */ public Watchdog(long timeout) { if (timeout < 1) { - throw new IllegalArgumentException("timeout less than 1."); + throw new IllegalArgumentException(ERROR_INVALID_TIMEOUT); } this.timeout = timeout; } @@ -51,6 +60,7 @@ * @param to the timeout observer to add. */ public void addTimeoutObserver(TimeoutObserver to) { + //no need to synchronize, as Vector is always synchronized observers.addElement(to); } @@ -59,11 +69,13 @@ * @param to the timeout observer to remove. */ public void removeTimeoutObserver(TimeoutObserver to) { + //no need to synchronize, as Vector is always synchronized observers.removeElement(to); } /** * Inform the observers that a timeout has occurred. + * This happens in the watchdog thread. */ protected final void fireTimeoutOccured() { Enumeration e = observers.elements(); --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]