git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@669464 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -38,6 +38,12 @@ Changes that could break older environments: | |||||
| to do so however using a new parameter. | to do so however using a new parameter. | ||||
| Bugzilla report 33969. | Bugzilla report 33969. | ||||
| * A lock in Project ensured that a BuildListener's messageLogged | |||||
| method was only ever executed by a single thread at a time, while | |||||
| all other methods could be invoked by multiple threads | |||||
| simultaniously (while within <parallel>, for example). This lock is | |||||
| no longer in place, messageLogged should be made thread-safe now. | |||||
| Fixed bugs: | Fixed bugs: | ||||
| ----------- | ----------- | ||||
| @@ -63,6 +69,10 @@ Fixed bugs: | |||||
| characters in them. | characters in them. | ||||
| Bugzilla report 45190 | Bugzilla report 45190 | ||||
| * A deadlock could occur if a BuildListener tried to access an Ant property | |||||
| within messageLogged while a different thread also accessed one. | |||||
| Bugzilla report 45194 | |||||
| Other changes: | Other changes: | ||||
| -------------- | -------------- | ||||
| @@ -498,6 +498,11 @@ not access System.out and System.err directly. It must use the streams with whic | |||||
| been configured. | been configured. | ||||
| </p> | </p> | ||||
| <p><b>Note2:</b> All methods of a BuildListener except for the "Build | |||||
| Started" and "Build Finished" events may occur on several threads | |||||
| simultaneously - for example while Ant is executing | |||||
| a <code><parallel></code> task.</p> | |||||
| <hr> | <hr> | ||||
| <h2><a name="integration">Source code integration</a></h2> | <h2><a name="integration">Source code integration</a></h2> | ||||
| @@ -48,7 +48,7 @@ public class NoBannerLogger extends DefaultLogger { | |||||
| * @param event A BuildEvent containing target information. | * @param event A BuildEvent containing target information. | ||||
| * Must not be <code>null</code>. | * Must not be <code>null</code>. | ||||
| */ | */ | ||||
| public void targetStarted(BuildEvent event) { | |||||
| public synchronized void targetStarted(BuildEvent event) { | |||||
| targetName = extractTargetName(event); | targetName = extractTargetName(event); | ||||
| } | } | ||||
| @@ -67,7 +67,7 @@ public class NoBannerLogger extends DefaultLogger { | |||||
| * | * | ||||
| * @param event Ignored in this implementation. | * @param event Ignored in this implementation. | ||||
| */ | */ | ||||
| public void targetFinished(BuildEvent event) { | |||||
| public synchronized void targetFinished(BuildEvent event) { | |||||
| targetName = null; | targetName = null; | ||||
| } | } | ||||
| @@ -88,9 +88,11 @@ public class NoBannerLogger extends DefaultLogger { | |||||
| return; | return; | ||||
| } | } | ||||
| if (null != targetName) { | |||||
| out.println(StringUtils.LINE_SEP + targetName + ":"); | |||||
| targetName = null; | |||||
| synchronized (this) { | |||||
| if (null != targetName) { | |||||
| out.println(StringUtils.LINE_SEP + targetName + ":"); | |||||
| targetName = null; | |||||
| } | |||||
| } | } | ||||
| super.messageLogged(event); | super.messageLogged(event); | ||||
| @@ -172,6 +172,14 @@ public class Project implements ResourceFactory { | |||||
| /** List of listeners to notify of build events. */ | /** List of listeners to notify of build events. */ | ||||
| private Vector listeners = new Vector(); | private Vector listeners = new Vector(); | ||||
| /** for each thread, record whether it is currently executing | |||||
| messageLogged */ | |||||
| private final ThreadLocal isLoggingMessage = new ThreadLocal() { | |||||
| protected Object initialValue() { | |||||
| return Boolean.FALSE; | |||||
| } | |||||
| }; | |||||
| /** | /** | ||||
| * The Ant core classloader--may be <code>null</code> if using | * The Ant core classloader--may be <code>null</code> if using | ||||
| * parent classloader. | * parent classloader. | ||||
| @@ -201,11 +209,6 @@ public class Project implements ResourceFactory { | |||||
| */ | */ | ||||
| private boolean keepGoingMode = false; | private boolean keepGoingMode = false; | ||||
| /** | |||||
| * Flag which catches Listeners which try to use System.out or System.err . | |||||
| */ | |||||
| private boolean loggingMessage = false; | |||||
| /** | /** | ||||
| * Set the input handler. | * Set the input handler. | ||||
| * | * | ||||
| @@ -2144,8 +2147,7 @@ public class Project implements ResourceFactory { | |||||
| } else { | } else { | ||||
| event.setMessage(message, priority); | event.setMessage(message, priority); | ||||
| } | } | ||||
| synchronized (this) { | |||||
| if (loggingMessage) { | |||||
| if (isLoggingMessage.get() != Boolean.FALSE) { | |||||
| /* | /* | ||||
| * One of the Listeners has attempted to access | * One of the Listeners has attempted to access | ||||
| * System.err or System.out. | * System.err or System.out. | ||||
| @@ -2162,16 +2164,15 @@ public class Project implements ResourceFactory { | |||||
| return; | return; | ||||
| } | } | ||||
| try { | try { | ||||
| loggingMessage = true; | |||||
| isLoggingMessage.set(Boolean.TRUE); | |||||
| Iterator iter = listeners.iterator(); | Iterator iter = listeners.iterator(); | ||||
| while (iter.hasNext()) { | while (iter.hasNext()) { | ||||
| BuildListener listener = (BuildListener) iter.next(); | BuildListener listener = (BuildListener) iter.next(); | ||||
| listener.messageLogged(event); | listener.messageLogged(event); | ||||
| } | } | ||||
| } finally { | } finally { | ||||
| loggingMessage = false; | |||||
| isLoggingMessage.set(Boolean.FALSE); | |||||
| } | } | ||||
| } | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -34,7 +34,7 @@ import org.apache.tools.ant.Task; | |||||
| public class Log4jListener implements BuildListener { | public class Log4jListener implements BuildListener { | ||||
| /** Indicates if the listener was initialized. */ | /** Indicates if the listener was initialized. */ | ||||
| private boolean initialized = false; | |||||
| private final boolean initialized; | |||||
| /** | /** | ||||
| * log category we log into | * log category we log into | ||||