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]

Reply via email to