LOG4J2-1080 bugfix: AsyncAppender should only delegate to AsyncEventRouter if queue is full and blocking=true
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/072cbd27 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/072cbd27 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/072cbd27 Branch: refs/heads/master Commit: 072cbd270e4323ed9da46b59f66e8eafdf59354c Parents: 00a51fc Author: rpopma <[email protected]> Authored: Sat May 7 02:59:21 2016 +0900 Committer: rpopma <[email protected]> Committed: Sat May 7 02:59:21 2016 +0900 ---------------------------------------------------------------------- .../log4j/core/appender/AsyncAppender.java | 39 ++++++++------------ 1 file changed, 16 insertions(+), 23 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/072cbd27/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppender.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppender.java index b6670d6..5c89957 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppender.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AsyncAppender.java @@ -148,8 +148,17 @@ public final class AsyncAppender extends AbstractAppender { if (!Constants.FORMAT_MESSAGES_IN_BACKGROUND) { // LOG4J2-898: user may choose logEvent.getMessage().getFormattedMessage(); // LOG4J2-763: ask message to freeze parameters } - final EventRoute route = asyncEventRouter.getRoute(thread.getId(), logEvent.getLevel()); - route.logMessage(this, logEvent); + final Log4jLogEvent memento = Log4jLogEvent.createMemento(logEvent, includeLocation); + if (!queue.offer(memento)) { + if (blocking) { + // delegate to the event router (which may discard, enqueue and block, or log in current thread) + final EventRoute route = asyncEventRouter.getRoute(thread.getId(), memento.getLevel()); + route.logMessage(this, memento); + } else { + error("Appender " + getName() + " is unable to write primary appenders. queue is full"); + logToErrorAppenderIfNecessary(false, memento); + } + } } /** @@ -169,29 +178,13 @@ public final class AsyncAppender extends AbstractAppender { * @param logEvent the event to log */ public void logMessageInBackgroundThread(final LogEvent logEvent) { - final boolean success = blocking ? enqueueOrBlockIfQueueFull(logEvent) : enqueueOrDropIfQueueFull(logEvent); - logToErrorAppenderIfNecessary(success, logEvent); - } - - private boolean enqueueOrBlockIfQueueFull(final LogEvent logEvent) { - boolean appendSuccessful; - final Log4jLogEvent frozenLogEvent = Log4jLogEvent.createMemento(logEvent, includeLocation); try { // wait for free slots in the queue - queue.put(frozenLogEvent); - appendSuccessful = true; + queue.put(logEvent); } catch (final InterruptedException e) { - appendSuccessful = handleInterruptedException(frozenLogEvent); + final boolean appendSuccessful = handleInterruptedException(logEvent); + logToErrorAppenderIfNecessary(appendSuccessful, logEvent); } - return appendSuccessful; - } - - private boolean enqueueOrDropIfQueueFull(final LogEvent logEvent) { - final boolean appendSuccessful = queue.offer(Log4jLogEvent.createMemento(logEvent, includeLocation)); - if (!appendSuccessful) { - error("Appender " + getName() + " is unable to write primary appenders. queue is full"); - } - return appendSuccessful; } // LOG4J2-1049: Some applications use Thread.interrupt() to send @@ -205,8 +198,8 @@ public final class AsyncAppender extends AbstractAppender { // This may interfere with the application's expectation of // being interrupted, so when we are done, we set the interrupted // flag again. - private boolean handleInterruptedException(final Log4jLogEvent frozenLogEvent) { - final boolean appendSuccessful = queue.offer(frozenLogEvent); + private boolean handleInterruptedException(final LogEvent memento) { + final boolean appendSuccessful = queue.offer(memento); if (!appendSuccessful) { LOGGER.warn("Interrupted while waiting for a free slot in the AsyncAppender LogEvent-queue {}", getName());
