You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2018/03/01 00:21:14 UTC
logging-log4j2 git commit: [LOG4J2-2276]
ConcurrentModificationException from
org.apache.logging.log4j.status.StatusLogger.<
clinit>(StatusLogger.java:71).
Repository: logging-log4j2
Updated Branches:
refs/heads/release-2.x a10da6d43 -> a07176b6a
[LOG4J2-2276] ConcurrentModificationException from
org.apache.logging.log4j.status.StatusLogger.<clinit>(StatusLogger.java:71).
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/a07176b6
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/a07176b6
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/a07176b6
Branch: refs/heads/release-2.x
Commit: a07176b6a96eb062a92b6fd167332ea2bb22fbf4
Parents: a10da6d
Author: Gary Gregory <ga...@gmail.com>
Authored: Wed Feb 28 17:21:10 2018 -0700
Committer: Gary Gregory <ga...@gmail.com>
Committed: Wed Feb 28 17:21:10 2018 -0700
----------------------------------------------------------------------
.../util/SystemPropertiesPropertySource.java | 19 ++++--
.../SystemPropertiesPropertySourceTest.java | 72 ++++++++++++++++++++
src/changes/changes.xml | 3 +
3 files changed, 90 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/a07176b6/log4j-api/src/main/java/org/apache/logging/log4j/util/SystemPropertiesPropertySource.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/SystemPropertiesPropertySource.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/SystemPropertiesPropertySource.java
index af10fb0..627b968 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/SystemPropertiesPropertySource.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/SystemPropertiesPropertySource.java
@@ -16,7 +16,8 @@
*/
package org.apache.logging.log4j.util;
-import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
/**
* PropertySource backed by the current system properties. Other than having a higher priority over normal properties,
@@ -26,17 +27,27 @@ import java.util.Map;
*/
public class SystemPropertiesPropertySource implements PropertySource {
+ private static final int DEFAULT_PRIORITY = 100;
private static final String PREFIX = "log4j2.";
@Override
public int getPriority() {
- return 100;
+ return DEFAULT_PRIORITY;
}
@Override
public void forEach(final BiConsumer<String, String> action) {
- for (final Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
- action.accept(((String) entry.getKey()), ((String) entry.getValue()));
+ final Properties properties = System.getProperties();
+ // Lock properties only long enough to get a thread-safe SAFE snapshot of its current keys, an array.
+ final Object[] keySet;
+ synchronized (properties) {
+ keySet = properties.keySet().toArray();
+ }
+ // Then traverse for an unknown amount of time.
+ // Some keys may now be absent, in which case, the value is null.
+ for (final Object key : keySet) {
+ final String keyStr = Objects.toString(key, null);
+ action.accept(keyStr, properties.getProperty(keyStr));
}
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/a07176b6/log4j-api/src/test/java/org/apache/logging/log4j/util/SystemPropertiesPropertySourceTest.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/test/java/org/apache/logging/log4j/util/SystemPropertiesPropertySourceTest.java b/log4j-api/src/test/java/org/apache/logging/log4j/util/SystemPropertiesPropertySourceTest.java
new file mode 100644
index 0000000..e492e4a
--- /dev/null
+++ b/log4j-api/src/test/java/org/apache/logging/log4j/util/SystemPropertiesPropertySourceTest.java
@@ -0,0 +1,72 @@
+package org.apache.logging.log4j.util;
+
+import java.util.Properties;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.junit.Test;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+/**
+ * Tests https://issues.apache.org/jira/browse/LOG4J2-2276.
+ */
+public class SystemPropertiesPropertySourceTest {
+
+ private static final int ITERATIONS = 10000;
+
+ /**
+ * Tests avoiding a ConcurrentModificationException. For example:
+ *
+ * <pre>
+ * java.util.ConcurrentModificationException
+ * at java.util.Hashtable$Enumerator.next(Hashtable.java:1167)
+ * at org.apache.logging.log4j.util.SystemPropertiesPropertySource.forEach(SystemPropertiesPropertySource.java:38)
+ * at org.apache.logging.log4j.util.SystemPropertiesPropertySourceTest.testMultiThreadedAccess(SystemPropertiesPropertySourceTest.java:47)
+ * </pre>
+ */
+ @Test
+ public void testMultiThreadedAccess() throws InterruptedException, ExecutionException {
+ ExecutorService threadPool = Executors.newSingleThreadExecutor();
+ try {
+ Future<?> future = threadPool.submit(new Runnable() {
+
+ @Override
+ public void run() {
+ final Properties properties = System.getProperties();
+ for (int i = 0; i < ITERATIONS; i++) {
+ properties.setProperty("FOO_" + i, "BAR");
+ }
+ }
+ });
+ for (int i = 0; i < ITERATIONS; i++)
+ new SystemPropertiesPropertySource().forEach(new BiConsumer<String, String>() {
+ @Override
+ public void accept(final String key, final String value) {
+ // nothing
+ }
+ });
+ future.get();
+ } finally {
+ threadPool.shutdown();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/a07176b6/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index d4bff2b..b8ec985 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -207,6 +207,9 @@
<action issue="LOG4J2-2270" dev="ggregory" type="fix" due-to="Cyril Martin">
Strings::join, when called with [null] returns "null" instead of EMPTY.
</action>
+ <action issue="LOG4J2-2276" dev="ggregory" type="fix" due-to="Sean Baxter">
+ ConcurrentModificationException from org.apache.logging.log4j.status.StatusLogger.<clinit>(StatusLogger.java:71).
+ </action>
</release>
<release version="2.10.0" date="2017-11-18" description="GA Release 2.10.0">
<action issue="LOG4J2-2120" dev="mikes" type="add" due-to="Carter Douglas Kozak">