This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/9.0.x by this push:
new f57532446f Ensure atomic session persistence in FileStore
f57532446f is described below
commit f57532446f9d159cb1fa73a8cb251945bb0ab655
Author: Mark Thomas <[email protected]>
AuthorDate: Wed Jun 17 08:48:43 2026 +0100
Ensure atomic session persistence in FileStore
Based on #1016 by sahvx655-wq
---
java/org/apache/catalina/session/FileStore.java | 21 +++++++++++++++++++--
webapps/docs/changelog.xml | 4 ++++
2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/java/org/apache/catalina/session/FileStore.java
b/java/org/apache/catalina/session/FileStore.java
index 13b160f9bf..6ff91bfcfd 100644
--- a/java/org/apache/catalina/session/FileStore.java
+++ b/java/org/apache/catalina/session/FileStore.java
@@ -24,6 +24,9 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
+import java.nio.file.AtomicMoveNotSupportedException;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
@@ -270,15 +273,29 @@ public final class FileStore extends StoreBase {
.trace(sm.getString(getStoreName() + ".saving",
session.getIdInternal(), file.getAbsolutePath()));
}
+ File tempFile = new File(file.getAbsolutePath() + ".tmp");
+
Lock writeLock =
sessionLocksById.getLock(session.getIdInternal()).writeLock();
writeLock.lock();
try {
- try (FileOutputStream fos = new
FileOutputStream(file.getAbsolutePath());
+ try (FileOutputStream fos = new FileOutputStream(tempFile);
ObjectOutputStream oos = new ObjectOutputStream(new
BufferedOutputStream(fos))) {
((StandardSession) session).writeObjectData(oos);
}
+ try {
+ Files.move(tempFile.toPath(), file.toPath(),
StandardCopyOption.REPLACE_EXISTING,
+ StandardCopyOption.ATOMIC_MOVE);
+ } catch (AtomicMoveNotSupportedException e) {
+ Files.move(tempFile.toPath(), file.toPath(),
StandardCopyOption.REPLACE_EXISTING);
+ }
} finally {
- writeLock.unlock();
+ try {
+ if (tempFile.exists() && !tempFile.delete()) {
+ log.warn(sm.getString("fileStore.deleteFailed", tempFile));
+ }
+ } finally {
+ writeLock.unlock();
+ }
}
}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index f167aec9da..3d2a50a815 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -291,6 +291,10 @@
<code>MemoryUserDatabase</code> to avoid concurrency issues with the
file save operations. (markt)
</fix>
+ <fix>
+ Ensure atomic session persistence in <code>FileStore</code>. Based on
+ pull request <pr>1016</pr> by sahvx655-wq. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]