You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by "Robert Schaft (JIRA)" <ji...@apache.org> on 2015/06/10 15:47:00 UTC

[jira] [Created] (LOG4J2-1049) AsyncAppender eats my Interrupt

Robert Schaft created LOG4J2-1049:
-------------------------------------

             Summary: AsyncAppender eats my Interrupt
                 Key: LOG4J2-1049
                 URL: https://issues.apache.org/jira/browse/LOG4J2-1049
             Project: Log4j 2
          Issue Type: Bug
          Components: Appenders
    Affects Versions: 2.3, 2.2
         Environment: Java 7, Windows
            Reporter: Robert Schaft


I wrote a LoggingThread that will be stopped by sending loggingThread.interrupt() from another Thread.

{code:title=LoggingThread.java}
class LoggingThread extends Thread {
  private final static Logger LOGGER = LoggerFactory.getLogger(LoggingThread .class);
  public void run() {
    while (!Thread.currentThread().isInterrupted()) {
      LOGGER.debug("{} is logging {}", this, "nothing");
    }
  }
}
{code}

Unfortunately, loggingThread.interrupt() is sometimes set before AsyncAppender.append() or at the beginning of that.
{code:title=AsyncAppender#append() line 153}
try {
  // wait for free slots in the queue
  queue.put(Log4jLogEvent.serialize(coreEvent, includeLocation));
  appendSuccessful = true;
} catch (final InterruptedException e) {
  LOGGER.warn("Interrupted while waiting for a free slot in the AsyncAppender LogEvent-queue {}",
  getName());
}
{code}
This will make queue.put throw an InterruptedException and remove the interrupted flag of the current flag.

I suggest a simple bugfix: Call Thread by Thread.currentThread().interrupt() in the catch clause. This will reset the interrupted flag of the current Thread.

A more complex bugfix which doesn't loose a message:
{code:title=AsyncAppender#append() line 153}
Serializable serialized = Log4jLogEvent.serialize(coreEvent, includeLocation);
try {
  // wait for free slots in the queue
  queue.put(serialized);
  appendSuccessful = true;
} catch (final InterruptedException e) {
  try {
    // The interrupt is catched and the interrupted flag is unset.
    // Therefore offer() won't return with an InterruptedException
    // unless another Thread sends again an interrupt.
    // Use a timeout to handle the case where the Interrupt e
    // was really meant for a hanging put() and not just 
    // coincidently sent at the same time.
    // If the put() was really hanging,
    // offer() would return with false after 10ms and no second
    // external interrupt() is required
    appendSuccessful = queue.offer(serialized, 10L, TimeUnit.MILLISECONDS);
  } catch (final InterruptedException e2) {
    // queue.put is really hanging and someone 
  }
  if (!appendSuccessful) {
    LOGGER.warn("Interrupted while waiting for a free slot in the AsyncAppender LogEvent-queue {}",
    getName());
  }
  // set the interrupted flag again.
  Thread.currentThread().interrupt();
}
{code}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org