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.
+
+
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;
}
}