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:27 UTC
[logging-log4j2] 01/03: LOG4J2-2895: Async logging avoids blocking
on Log4jThreads
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 2a5665ef8216e753ae9cb4b6c40c8cb1342e6a04
Author: Carter Kozak <ck...@apache.org>
AuthorDate: Thu Jul 16 16:12:35 2020 -0400
LOG4J2-2895: Async logging avoids blocking on Log4jThreads
---
.../logging/log4j/core/async/AsyncLoggerConfigDisruptor.java | 8 +++++++-
.../apache/logging/log4j/core/async/AsyncLoggerDisruptor.java | 8 +++++++-
.../logging/log4j/core/async/DefaultAsyncQueueFullPolicy.java | 9 ++++++++-
src/changes/changes.xml | 3 +++
4 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
index be34e09..a506619 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
@@ -27,6 +27,7 @@ import org.apache.logging.log4j.core.impl.LogEventFactory;
import org.apache.logging.log4j.core.impl.MutableLogEvent;
import org.apache.logging.log4j.core.impl.ReusableLogEventFactory;
import org.apache.logging.log4j.core.jmx.RingBufferAdmin;
+import org.apache.logging.log4j.core.util.Log4jThread;
import org.apache.logging.log4j.core.util.Log4jThreadFactory;
import org.apache.logging.log4j.core.util.Throwables;
import org.apache.logging.log4j.message.ReusableMessage;
@@ -383,7 +384,12 @@ public class AsyncLoggerConfigDisruptor extends AbstractLifeCycle implements Asy
private boolean synchronizeEnqueueWhenQueueFull() {
return DisruptorUtil.ASYNC_CONFIG_SYNCHRONIZE_ENQUEUE_WHEN_QUEUE_FULL
// Background thread must never block
- && backgroundThreadId != Thread.currentThread().getId();
+ && backgroundThreadId != Thread.currentThread().getId()
+ // Threads owned by log4j are most likely to result in
+ // deadlocks because they generally consume events.
+ // This prevents deadlocks between AsyncLoggerContext
+ // disruptors.
+ && !(Thread.currentThread() instanceof Log4jThread);
}
@Override
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 e8c0121..c51defa 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
@@ -25,6 +25,7 @@ import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.core.AbstractLifeCycle;
import org.apache.logging.log4j.core.jmx.RingBufferAdmin;
+import org.apache.logging.log4j.core.util.Log4jThread;
import org.apache.logging.log4j.core.util.Log4jThreadFactory;
import org.apache.logging.log4j.core.util.Throwables;
@@ -281,7 +282,12 @@ class AsyncLoggerDisruptor extends AbstractLifeCycle {
private boolean synchronizeEnqueueWhenQueueFull() {
return DisruptorUtil.ASYNC_LOGGER_SYNCHRONIZE_ENQUEUE_WHEN_QUEUE_FULL
// Background thread must never block
- && backgroundThreadId != Thread.currentThread().getId();
+ && backgroundThreadId != Thread.currentThread().getId()
+ // Threads owned by log4j are most likely to result in
+ // deadlocks because they generally consume events.
+ // This prevents deadlocks between AsyncLoggerContext
+ // disruptors.
+ && !(Thread.currentThread() instanceof Log4jThread);
}
private void logWarningOnNpeFromDisruptorPublish(final RingBufferLogEventTranslator translator) {
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DefaultAsyncQueueFullPolicy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DefaultAsyncQueueFullPolicy.java
index 1d48113..d3d53e1 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DefaultAsyncQueueFullPolicy.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DefaultAsyncQueueFullPolicy.java
@@ -17,6 +17,7 @@
package org.apache.logging.log4j.core.async;
import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.util.Log4jThread;
/**
* Default router: enqueue the event for asynchronous logging in the background thread, unless the current thread is the
@@ -29,7 +30,13 @@ public class DefaultAsyncQueueFullPolicy implements AsyncQueueFullPolicy {
// LOG4J2-471: prevent deadlock when RingBuffer is full and object
// being logged calls Logger.log() from its toString() method
- if (Thread.currentThread().getId() == backgroundThreadId) {
+ Thread currentThread = Thread.currentThread();
+ if (currentThread.getId() == backgroundThreadId
+ // Threads owned by log4j are most likely to result in
+ // deadlocks because they generally consume events.
+ // This prevents deadlocks between AsyncLoggerContext
+ // disruptors.
+ || currentThread instanceof Log4jThread) {
return EventRoute.SYNCHRONOUS;
}
return EventRoute.ENQUEUE;
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 9def922..51d10a3 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -75,6 +75,9 @@
<action dev="ggregory" type="update">
Update tests commons-io:commons-io 2.6 -> 2.7.
</action>
+ <action issue="LOG4J2-2895" dev="ckozak" type="fix">
+ Fix potential deadlock in asynchronous logging by avoiding blocking for queue space on Log4jThreads
+ </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">