Uploaded image for project: 'logback'
  1. logback
  2. LOGBACK-1087

ConcurrentModificationException is thrown from BasicStatusManager.fireStatusAddEvent on iteration through status listeners whilst StatusListener is removed in a separate thread

    XMLWordPrintable

Details

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Major Major
    • None
    • 1.1.2, 1.1.3
    • logback-classic
    • None

    Description

      ConcurrentModificationException can be thrown whilst status event is fired out into registered StatusListeners but one of the listener is removed at the same time from a different thread.

      An example of stack trace for the issue is provided below

      11:31:11,081 |-ERROR in ch.qos.logback.core.rolling.RollingFileAppender[logfile] - Appender [logfile] failed to append. java.util.ConcurrentModificationException
          at java.util.ConcurrentModificationException
          at     at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
          at     at java.util.ArrayList$Itr.next(ArrayList.java:831)
          at     at ch.qos.logback.core.BasicStatusManager.fireStatusAddEvent(BasicStatusManager.java:86)
          at     at ch.qos.logback.core.BasicStatusManager.add(BasicStatusManager.java:59)
          at     at ch.qos.logback.core.recovery.ResilientOutputStreamBase.addStatus(ResilientOutputStreamBase.java:157)
          at     at ch.qos.logback.core.recovery.ResilientOutputStreamBase.addStatusIfCountNotOverLimit(ResilientOutputStreamBase.java:138)
          at     at ch.qos.logback.core.recovery.ResilientOutputStreamBase.postIOFailure(ResilientOutputStreamBase.java:101)
          at     at ch.qos.logback.core.recovery.ResilientOutputStreamBase.flush(ResilientOutputStreamBase.java:82)
          at     at ch.qos.logback.core.encoder.LayoutWrappingEncoder.doEncode(LayoutWrappingEncoder.java:137)
          at     at ch.qos.logback.core.OutputStreamAppender.writeOut(OutputStreamAppender.java:194)
          at     at ch.qos.logback.core.FileAppender.writeOut(FileAppender.java:209)
          at     at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:219)
          at     at ch.qos.logback.core.rolling.RollingFileAppender.subAppend(RollingFileAppender.java:182)
          at     at ch.qos.logback.core.OutputStreamAppender.append(OutputStreamAppender.java:103)
          at     at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:88)
          at     at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:48)
          at     at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:273)
          at     at ch.qos.logback.classic.Logger.callAppenders(Logger.java:260)
          at     at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:442)
          at     at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:396)
          at     at ch.qos.logback.classic.Logger.error(Logger.java:559)
      

      The easiest way to reproduce it would be to implement status listener unregistering itself from addStatusEvent:

      class MyListener implements StatusListener
      {
        private StatusManager _statusManager;
        public MyListener(StatusManager statusManager)
        {
          _statusManager = statusManager;
        }
      
        @Override
        public void addStatusEvent(Status status)
        {
          _statusManager.remove(this);
        }
      }
      
      

      The issue affects the application creating and removing Appenders dynamically and registering/unregistering StatusListeners on appender creation and removing accordingly.

      Attachments

        Activity

          People

            logback-dev Logback dev list
            alex.rufous Alex
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated: