diff --git a/docs/manual/develop.html b/docs/manual/develop.html index 60f22b416..a19e1c198 100644 --- a/docs/manual/develop.html +++ b/docs/manual/develop.html @@ -336,6 +336,14 @@ If you wish to attach a listener from the command line you may use the

will run Ant with a listener that generates an XML representation of the build progress. This listener is included with Ant, as is the default listener, which generates the logging to standard output.

+

Note: A listener must not access System.out and System.err directly since ouput on +these streams is redirected by Ant's core to the build event system. Accessing these +streams can cause an infinite loop in Ant. Depending on the version of Ant, this will +either cause the build to terminate or the Java VM to run out of Stack space. A logger, also, may +not access System.out and System.err directly. It must use the streams with which it has +been configured. +

+

Source code integration

diff --git a/src/main/org/apache/tools/ant/Project.java b/src/main/org/apache/tools/ant/Project.java index 97486fd30..e72f4ec00 100644 --- a/src/main/org/apache/tools/ant/Project.java +++ b/src/main/org/apache/tools/ant/Project.java @@ -253,6 +253,11 @@ public class Project { /** Instance of a utility class to use for file operations. */ private FileUtils fileUtils; + /** + * Flag which catches Listeners which try to use System.out or System.err + */ + private boolean loggingMessage = false; + /** * Creates a new Ant project. */ @@ -2055,9 +2060,18 @@ public class Project { int priority) { event.setMessage(message, priority); Vector listeners = getBuildListeners(); - for (int i = 0; i < listeners.size(); i++) { - BuildListener listener = (BuildListener) listeners.elementAt(i); - listener.messageLogged(event); + synchronized(this) { + if (loggingMessage) { + throw new BuildException("Listener attempted to access " + + (priority == MSG_ERR ? "System.err" : "System.out") + + " - infinite loop terminated"); + } + loggingMessage = true; + for (int i = 0; i < listeners.size(); i++) { + BuildListener listener = (BuildListener) listeners.elementAt(i); + listener.messageLogged(event); + } + loggingMessage = false; } }