Repository: ant Updated Branches: refs/heads/master 33d20f436 -> 1388e372a
make LocalPropertyStack thread-safe https://issues.apache.org/bugzilla/show_bug.cgi?id=55074 Project: http://git-wip-us.apache.org/repos/asf/ant/repo Commit: http://git-wip-us.apache.org/repos/asf/ant/commit/1388e372 Tree: http://git-wip-us.apache.org/repos/asf/ant/tree/1388e372 Diff: http://git-wip-us.apache.org/repos/asf/ant/diff/1388e372 Branch: refs/heads/master Commit: 1388e372a9eb6cc6c463fbda928a10afd17b6d0a Parents: 33d20f4 Author: Stefan Bodewig <[email protected]> Authored: Wed Feb 11 14:26:00 2015 +0100 Committer: Stefan Bodewig <[email protected]> Committed: Wed Feb 11 14:26:00 2015 +0100 ---------------------------------------------------------------------- WHATSNEW | 4 ++ .../tools/ant/property/LocalPropertyStack.java | 45 +++++++++++++------- 2 files changed, 33 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ant/blob/1388e372/WHATSNEW ---------------------------------------------------------------------- diff --git a/WHATSNEW b/WHATSNEW index b25e43a..1cdbd44 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -77,6 +77,10 @@ Fixed bugs: * complete-ant-cmd.pl now also completes tasks without a description. Bugzilla Report 57542 + * LocalPropertyStack could run into ConcurrentModificationException + when tasks spawned new child threads that accessed the properties. + Bugzilla Report 55074 + Other changes: -------------- http://git-wip-us.apache.org/repos/asf/ant/blob/1388e372/src/main/org/apache/tools/ant/property/LocalPropertyStack.java ---------------------------------------------------------------------- diff --git a/src/main/org/apache/tools/ant/property/LocalPropertyStack.java b/src/main/org/apache/tools/ant/property/LocalPropertyStack.java index cced579..482f28c 100644 --- a/src/main/org/apache/tools/ant/property/LocalPropertyStack.java +++ b/src/main/org/apache/tools/ant/property/LocalPropertyStack.java @@ -17,10 +17,9 @@ */ package org.apache.tools.ant.property; - -import java.util.HashMap; import java.util.LinkedList; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.apache.tools.ant.PropertyHelper; @@ -31,6 +30,7 @@ import org.apache.tools.ant.PropertyHelper; */ public class LocalPropertyStack { private final LinkedList<Map<String, Object>> stack = new LinkedList<Map<String, Object>>(); + private final Object LOCK = new Object(); // -------------------------------------------------- // @@ -43,8 +43,11 @@ public class LocalPropertyStack { * @param property the name of the local property. */ public void addLocal(String property) { - if (!stack.isEmpty()) { - stack.getFirst().put(property, NullReturn.NULL); + synchronized (LOCK) { + Map<String, Object> map = stack.peek(); + if (map != null) { + map.put(property, NullReturn.NULL); + } } } @@ -52,14 +55,18 @@ public class LocalPropertyStack { * Enter the local scope. */ public void enterScope() { - stack.addFirst(new HashMap<String, Object>()); + synchronized (LOCK) { + stack.addFirst(new ConcurrentHashMap<String, Object>()); + } } /** * Exit the local scope. */ public void exitScope() { - stack.removeFirst().clear(); + synchronized (LOCK) { + stack.removeFirst().clear(); + } } // -------------------------------------------------- @@ -73,9 +80,11 @@ public class LocalPropertyStack { * @return a copy. */ public LocalPropertyStack copy() { - LocalPropertyStack ret = new LocalPropertyStack(); - ret.stack.addAll(stack); - return ret; + synchronized (LOCK) { + LocalPropertyStack ret = new LocalPropertyStack(); + ret.stack.addAll(stack); + return ret; + } } // -------------------------------------------------- @@ -91,10 +100,12 @@ public class LocalPropertyStack { * @return Object value. */ public Object evaluate(String property, PropertyHelper helper) { - for (Map<String, Object> map : stack) { - Object ret = map.get(property); - if (ret != null) { - return ret; + synchronized (LOCK) { + for (Map<String, Object> map : stack) { + Object ret = map.get(property); + if (ret != null) { + return ret; + } } } return null; @@ -137,9 +148,11 @@ public class LocalPropertyStack { } private Map<String, Object> getMapForProperty(String property) { - for (Map<String, Object> map : stack) { - if (map.get(property) != null) { - return map; + synchronized (LOCK) { + for (Map<String, Object> map : stack) { + if (map.get(property) != null) { + return map; + } } } return null;
