Details

    • Type: Bug
    • Status: Resolved
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 2.2, 2.3
    • Fix Version/s: 2.4
    • Component/s: Appenders
    • Labels:
    • Environment:

      Java 7, Windows

    • Flags:
      Patch

      Description

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

      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");
          }
        }
      }
      

      Unfortunately, loggingThread.interrupt() is sometimes set before AsyncAppender.append() or at the beginning of that.

      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());
      }
      

      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:

      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();
      }
      

        Attachments

          Activity

            People

            • Assignee:
              remkop@yahoo.com Remko Popma
              Reporter:
              robert.schaft Robert Schaft
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Time Tracking

                Estimated:
                Original Estimate - 48h
                48h
                Remaining:
                Remaining Estimate - 48h
                48h
                Logged:
                Time Spent - Not Specified
                Not Specified