Details
-
Bug
-
Resolution: Unresolved
-
Major
-
None
-
1.1.2, 1.1.3
-
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.