This is an automated email from the ASF dual-hosted git repository.
ramanathan1504 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/main by this push:
new 463f9c0229 Reopen log file when rollover is unsuccessful (#3226)
(#4154)
463f9c0229 is described below
commit 463f9c02298bff6eaf3ead1cebd9973309eccfda
Author: Vasily Pelikh <[email protected]>
AuthorDate: Sun Jul 19 15:03:18 2026 +0300
Reopen log file when rollover is unsuccessful (#3226) (#4154)
Signed-off-by: Vasily Pelikh <[email protected]>
---
.../appender/rolling/RollingFileManagerTest.java | 53 ++++++++++++++++++----
.../core/appender/rolling/RollingFileManager.java | 22 ++++-----
2 files changed, 56 insertions(+), 19 deletions(-)
diff --git
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManagerTest.java
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManagerTest.java
index 79d8d82e64..431775e382 100644
---
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManagerTest.java
+++
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManagerTest.java
@@ -17,13 +17,16 @@
package org.apache.logging.log4j.core.appender.rolling;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import org.apache.logging.log4j.core.LoggerContext;
@@ -135,9 +138,6 @@ public class RollingFileManagerTest {
assertNotNull(manager);
manager.initialize();
- // Get the initialTime of this original log file
- final long initialTime = manager.getFileTime();
-
// Log something to ensure that the existing file size is > 0
final String testContent = "Test";
manager.writeToDestination(testContent.getBytes(StandardCharsets.US_ASCII), 0,
testContent.length());
@@ -145,11 +145,11 @@ public class RollingFileManagerTest {
// Trigger rollover that will fail
manager.rollover();
- // If the rollover fails, then the size should not be reset
- assertNotEquals(0, manager.getFileSize());
+ // If the rollover fails, then the log file should be unchanged
+ assertEquals(file.getAbsolutePath(), manager.getFileName());
- // The initialTime should not have changed
- assertEquals(initialTime, manager.getFileTime());
+ // The logged content should be unchanged
+ assertEquals(testContent, new
String(Files.readAllBytes(file.toPath()), StandardCharsets.US_ASCII));
}
@Test
@@ -185,4 +185,41 @@ public class RollingFileManagerTest {
manager.close();
}
}
+
+ @Test
+ @Issue("https://github.com/apache/logging-log4j2/issues/2592")
+ public void testRolloverOfDeletedFile() throws IOException {
+ final File file = File.createTempFile("testRolloverOfDeletedFile",
"log");
+ file.deleteOnExit();
+ final String testContent = "Test";
+ final Configuration configuration = new NullConfiguration();
+ try (final OutputStream os =
+ new ByteArrayOutputStream(); // use a dummy
OutputStream so that the real file can be deleted
+ final RollingFileManager manager = new RollingFileManager(
+ configuration,
+ null, // loggerContext
+ file.getAbsolutePath(),
+ "testRolloverOfDeletedFile.log.%d{yyyy-MM-dd}",
+ os,
+ true,
+ false,
+ 0,
+ System.currentTimeMillis(),
+ OnStartupTriggeringPolicy.createPolicy(1),
+ DefaultRolloverStrategy.newBuilder().build(),
+ file.getName(),
+ null,
+ null,
+ null,
+ null,
+ false,
+ ByteBuffer.allocate(256))) {
+ assertTrue(file.delete());
+ manager.rollover();
+ assertEquals(file.getAbsolutePath(), manager.getFileName());
+
manager.writeBytes(testContent.getBytes(StandardCharsets.US_ASCII), 0,
testContent.length());
+ manager.flush();
+ }
+ assertEquals(testContent, new
String(Files.readAllBytes(file.toPath()), StandardCharsets.US_ASCII));
+ }
}
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
index 28da0d0c92..b8ddb53da3 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
@@ -516,43 +516,43 @@ public class RollingFileManager extends FileManager {
private boolean rollover(final RolloverStrategy strategy) {
- boolean releaseRequired = false;
+ boolean outputStreamClosed = false;
try {
// Block until the asynchronous operation is completed.
semaphore.acquire();
- releaseRequired = true;
} catch (final InterruptedException e) {
logError("Thread interrupted while attempting to check rollover",
e);
- return false;
+ return outputStreamClosed;
}
- boolean success = true;
+ boolean asyncActionStarted = true;
try {
final RolloverDescription descriptor = strategy.rollover(this);
if (descriptor != null) {
writeFooter();
closeOutputStream();
+ outputStreamClosed = true;
+ boolean syncActionSuccess = true;
if (descriptor.getSynchronous() != null) {
LOGGER.debug("RollingFileManager executing synchronous
{}", descriptor.getSynchronous());
try {
- success = descriptor.getSynchronous().execute();
+ syncActionSuccess =
descriptor.getSynchronous().execute();
} catch (final Exception ex) {
- success = false;
+ syncActionSuccess = false;
logError("Caught error in synchronous task", ex);
}
}
- if (success && descriptor.getAsynchronous() != null) {
+ if (syncActionSuccess && descriptor.getAsynchronous() != null)
{
LOGGER.debug("RollingFileManager executing async {}",
descriptor.getAsynchronous());
asyncExecutor.execute(new
AsyncAction(descriptor.getAsynchronous(), this));
- releaseRequired = false;
+ asyncActionStarted = false;
}
- return success;
}
- return false;
+ return outputStreamClosed;
} finally {
- if (releaseRequired) {
+ if (asyncActionStarted) {
semaphore.release();
}
}