Index: log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java (revision 84cd5d4e1460bec390f58ca01585ccb4973ab10d) +++ log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java (date 1582640668972) @@ -289,14 +289,26 @@ if (!hasOutputStream() && !isCreateOnDemand()) { return; } - if (rollover(rolloverStrategy)) { - try { - size = 0; - initialTime = System.currentTimeMillis(); - createFileAfterRollover(); - } catch (final IOException e) { - logError("Failed to create file after rollover", e); + + boolean interrupted = Thread.interrupted(); // clear interrupted state + try { + if (interrupted) { + LOGGER.warn("RollingFileManager cleared thread interrupted state, continue to rollover"); + } + + if (rollover(rolloverStrategy)) { + try { + size = 0; + initialTime = System.currentTimeMillis(); + createFileAfterRollover(); + } catch (final IOException e) { + logError("Failed to create file after rollover", e); + } } + } finally { + if (interrupted) { // restore interrupted state + Thread.currentThread().interrupt(); + } } } Index: log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingFileAppenderInterruptedThreadTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingFileAppenderInterruptedThreadTest.java (date 1582708093876) +++ log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingFileAppenderInterruptedThreadTest.java (date 1582708093876) @@ -0,0 +1,78 @@ +package org.apache.logging.log4j.core.appender.rolling; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.Logger; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.appender.ConsoleAppender; +import org.apache.logging.log4j.core.appender.RollingFileAppender; +import org.apache.logging.log4j.core.config.Configurator; +import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder; +import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory; +import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration; +import org.apache.logging.log4j.junit.CleanFolders; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.File; + +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.instanceOf; + +/** + * Tests https://issues.apache.org/jira/browse/LOG4J2-1798 + */ +public class RollingFileAppenderInterruptedThreadTest { + + private static final String ROLLING_APPENDER_FILES_DIR = + "target/" + RollingFileAppenderInterruptedThreadTest.class.getSimpleName(); + + @Rule + public CleanFolders cleanFolders = new CleanFolders(true, false, 3, ROLLING_APPENDER_FILES_DIR); + + LoggerContext loggerContext; + + @Before + public void setUp() { + ConfigurationBuilder builder = ConfigurationBuilderFactory.newConfigurationBuilder(); + builder.setConfigurationName("LOG4J2-1798 test"); + + builder.add(builder.newAppender("consoleLog", "Console") + .addAttribute("target", ConsoleAppender.Target.SYSTEM_ERR)); + + builder.add(builder.newAppender("fileAppender", "RollingFile") + .addAttribute("filePattern", ROLLING_APPENDER_FILES_DIR + "/file-%i.log") + .add(builder.newLayout("PatternLayout").addAttribute("pattern", "%msg%n")) + .addComponent(builder.newComponent("SizeBasedTriggeringPolicy") + .addAttribute("size", "20B"))); // relatively small amount to trigger rotation quickly + + builder.add(builder.newRootLogger(Level.INFO) + .add(builder.newAppenderRef("consoleLog")) + .add(builder.newAppenderRef("fileAppender"))); + + loggerContext = Configurator.initialize(builder.build()); + } + + @After + public void tearDown() { + Configurator.shutdown(loggerContext); + loggerContext = null; + } + + @Test + public void testRolloverInInterruptedThread() { + Logger logger = loggerContext.getLogger(getClass().getName()); + + Assert.assertThat(logger.getAppenders().values(), hasItem(instanceOf(RollingFileAppender.class))); + + logger.info("Sending logging event 1"); // send first event to initialize rollover system + + Thread.currentThread().interrupt(); // mark thread as interrupted + logger.info("Sending logging event 2"); // send second event to trigger rotation, expecting 2 files in result + + Assert.assertTrue(new File(ROLLING_APPENDER_FILES_DIR, "file-1.log").exists()); + Assert.assertTrue(new File(ROLLING_APPENDER_FILES_DIR, "file-2.log").exists()); + } +}