You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ck...@apache.org on 2020/07/16 20:36:28 UTC

[logging-log4j2] 02/03: LOG4J2-2837: Disruptor and JUL no longer recursively start the AsyncLoggerDisruptor

This is an automated email from the ASF dual-hosted git repository.

ckozak pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 31340441e844383efe640e051a3d747a3ef9cd00
Author: Carter Kozak <ck...@apache.org>
AuthorDate: Thu Jul 16 16:17:20 2020 -0400

    LOG4J2-2837: Disruptor and JUL no longer recursively start the AsyncLoggerDisruptor
    
    Previously logging initialization would result in an AsyncLoggerContext
    initializing an AsyncLoggerDisruptor, which would access a logger from
    JUL, starting the process again. This change avoids recursive calls with
    a state check.
---
 .../log4j/core/async/AsyncLoggerDisruptor.java     |  5 ++
 log4j-jul/pom.xml                                  |  6 ++
 .../logging/log4j/jul/AsyncLoggerThreadsTest.java  | 66 ++++++++++++++++++++++
 src/changes/changes.xml                            |  4 ++
 4 files changed, 81 insertions(+)

diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerDisruptor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerDisruptor.java
index c51defa..377100e 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerDisruptor.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerDisruptor.java
@@ -86,6 +86,11 @@ class AsyncLoggerDisruptor extends AbstractLifeCycle {
                     contextName);
             return;
         }
+        if (isStarting()) {
+            LOGGER.trace("[{}] AsyncLoggerDisruptor is already starting.", contextName);
+            return;
+        }
+        setStarting();
         LOGGER.trace("[{}] AsyncLoggerDisruptor creating new disruptor for this context.", contextName);
         ringBufferSize = DisruptorUtil.calculateRingBufferSize("AsyncLogger.RingBufferSize");
         final WaitStrategy waitStrategy = DisruptorUtil.createWaitStrategy("AsyncLogger.WaitStrategy");
diff --git a/log4j-jul/pom.xml b/log4j-jul/pom.xml
index d29f12a..11d1c5c 100644
--- a/log4j-jul/pom.xml
+++ b/log4j-jul/pom.xml
@@ -60,6 +60,12 @@
       <artifactId>junit</artifactId>
       <scope>test</scope>
     </dependency>
+    <!-- Required for AsyncLogger testing -->
+    <dependency>
+      <groupId>com.lmax</groupId>
+      <artifactId>disruptor</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
diff --git a/log4j-jul/src/test/java/org/apache/logging/log4j/jul/AsyncLoggerThreadsTest.java b/log4j-jul/src/test/java/org/apache/logging/log4j/jul/AsyncLoggerThreadsTest.java
new file mode 100644
index 0000000..0ef1585
--- /dev/null
+++ b/log4j-jul/src/test/java/org/apache/logging/log4j/jul/AsyncLoggerThreadsTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+package org.apache.logging.log4j.jul;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.categories.AsyncLoggers;
+import org.apache.logging.log4j.core.CoreLoggerContexts;
+import org.apache.logging.log4j.core.async.AsyncLoggerContextSelector;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.util.Constants;
+import org.apache.logging.log4j.core.util.DummyNanoClock;
+import org.apache.logging.log4j.util.Strings;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+@Category(AsyncLoggers.class)
+public class AsyncLoggerThreadsTest {
+
+    @BeforeClass
+    public static void beforeClass() {
+        System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR,
+                AsyncLoggerContextSelector.class.getName());
+        System.setProperty("java.util.logging.manager", org.apache.logging.log4j.jul.LogManager.class.getName());
+    }
+
+    @AfterClass
+    public static void afterClass() {
+        System.clearProperty(Constants.LOG4J_CONTEXT_SELECTOR);
+        System.clearProperty("java.util.logging.manager");
+    }
+
+    @Test
+    public void testAsyncLoggerThreads() {
+        LogManager.getLogger("com.foo.Bar").info("log");
+        List<Thread> asyncLoggerThreads = Thread.getAllStackTraces().keySet().stream()
+                .filter(thread -> thread.getName().matches("Log4j2-TF.*AsyncLogger.*"))
+                .collect(Collectors.toList());
+        assertEquals(asyncLoggerThreads.toString(), 1, asyncLoggerThreads.size());
+    }
+}
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 51d10a3..c2c41ad 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -78,6 +78,10 @@
       <action issue="LOG4J2-2895" dev="ckozak" type="fix">
         Fix potential deadlock in asynchronous logging by avoiding blocking for queue space on Log4jThreads
       </action>
+      <action issue="LOG4J2-2837" dev="ckozak" type="fix">
+        Disruptor and JUL no longer recursively start the AsyncLoggerDisruptor
+        resulting in an extra disruptor background thread constantly waiting.
+      </action>
     </release>
     <release version="2.13.3" date="2020-05-10" description="GA Release 2.13.3">
       <action issue="LOG4J2-2838" dev="rgoers" type="fix">