From 37cf105bb344793a164900b1a09d678679e13946 Mon Sep 17 00:00:00 2001 From: "Jesse N. Glick" Date: Tue, 17 Nov 2009 23:39:22 +0000 Subject: [PATCH] Trying to improve robustness in and . Observed a long-running build randomly failing with text like this: [propertyfile] Updating property file: .../whatever.properties [subant] Failure for target 'something' of: ...module1/build.xml [subant] The following error occurred while executing this line: [subant] .../something.xml:123: java.lang.OutOfMemoryError: GC overhead limit exceeded [subant] Failure for target 'something' of: ...module2/build.xml [subant] The following error occurred while executing this line: [subant] ...module2/build.xml:12: The following error occurred while executing this line: [subant] .../something.xml:123: Syntax error in property: ${some.prope [subant] Failure for target 'something' of: ...module3/build.xml [etc., hundreds of times] Turns out that whatever.properties had been truncated at exactly 24k characters, in the middle of a line. Fixing to therefore collect all of what it plans to write, then write it. Also trying to make actually stop the build when it gets OOME, rather than continuing (probably in vain) just because failonerror="false" (which is intended to catch "normal" problems). ThreadDeath should also be rethrown, not logged as a subscript failure. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@881624 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/tools/ant/taskdefs/SubAnt.java | 4 +++ .../ant/taskdefs/optional/PropertyFile.java | 29 +++++++++++++------ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/main/org/apache/tools/ant/taskdefs/SubAnt.java b/src/main/org/apache/tools/ant/taskdefs/SubAnt.java index f3c72e4f2..5d336e209 100644 --- a/src/main/org/apache/tools/ant/taskdefs/SubAnt.java +++ b/src/main/org/apache/tools/ant/taskdefs/SubAnt.java @@ -307,6 +307,10 @@ public class SubAnt extends Task { log("Failure for target '" + subTarget + "' of: " + antfilename + "\n" + e.getMessage(), Project.MSG_WARN); + } catch (OutOfMemoryError e) { + throw e; + } catch (ThreadDeath e) { + throw e; } catch (Throwable e) { if (failOnError) { throw new BuildException(e); diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/PropertyFile.java b/src/main/org/apache/tools/ant/taskdefs/optional/PropertyFile.java index 847702362..47984e36f 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/PropertyFile.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/PropertyFile.java @@ -19,11 +19,12 @@ package org.apache.tools.ant.taskdefs.optional; import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.text.DateFormat; import java.text.DecimalFormat; import java.text.ParseException; @@ -37,7 +38,6 @@ import java.util.Properties; import java.util.Vector; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; -import org.apache.tools.ant.util.FileUtils; import org.apache.tools.ant.util.LayoutPreservingProperties; import org.apache.tools.ant.types.EnumeratedAttribute; @@ -233,14 +233,25 @@ public class PropertyFile extends Task { } private void writeFile() throws BuildException { - BufferedOutputStream bos = null; + // Write to RAM first, as an OOME could otherwise produce a truncated file: + ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { - bos = new BufferedOutputStream(new FileOutputStream(propertyfile)); - properties.store(bos, comment); - } catch (IOException ioe) { - throw new BuildException(ioe, getLocation()); - } finally { - FileUtils.close(bos); + properties.store(baos, comment); + } catch (IOException x) { // should not happen + throw new BuildException(x, getLocation()); + } + try { + OutputStream os = new FileOutputStream(propertyfile); + try { + os.write(baos.toByteArray()); + } catch (IOException x) { + propertyfile.delete(); // possibly corrupt + throw new BuildException(x, getLocation()); + } finally { + os.close(); + } + } catch (IOException x) { + throw new BuildException(x, getLocation()); } }