This is an automated email from the ASF dual-hosted git repository.

markt-asf pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 949b1bcd44ba36a2bc7f39ecf154a38b0f9a7983
Author: Mark Thomas <[email protected]>
AuthorDate: Mon Aug 17 12:43:05 2026 +0100

    Follow-up to 9a59ef2717. Fix concurrency issue.
---
 .../catalina/session/PersistentManagerBase.java    | 15 ++++++++-----
 .../apache/catalina/session/SortableSession.java   | 26 ++++++++++++++++++++++
 2 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/java/org/apache/catalina/session/PersistentManagerBase.java 
b/java/org/apache/catalina/session/PersistentManagerBase.java
index 13d6a1fa7d..756e90fd47 100644
--- a/java/org/apache/catalina/session/PersistentManagerBase.java
+++ b/java/org/apache/catalina/session/PersistentManagerBase.java
@@ -18,7 +18,6 @@ package org.apache.catalina.session;
 
 import java.io.IOException;
 import java.util.Arrays;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -808,11 +807,17 @@ public abstract class PersistentManagerBase extends 
ManagerBase implements Store
             log.debug(sm.getString("persistentManager.tooManyActive", 
Integer.valueOf(sessions.length)));
         }
 
+        // lastAccessedTimeInternal may change so need to use a snapshot to 
avoid various concurrency failures.
+        SortableSession[] sortedSessions = new 
SortableSession[sessions.length];
+        for (int i = 0; i < sessions.length; i++) {
+            sortedSessions[i] = new 
SortableSession(sessions[i].getLastAccessedTimeInternal(), sessions[i]);
+        }
+        Arrays.sort(sortedSessions);
+
         int toswap = sessions.length - limit;
-        Arrays.sort(sessions, 
Comparator.comparingLong(Session::getLastAccessedTimeInternal));
 
-        for (int i = 0; i < sessions.length && toswap > 0; i++) {
-            StandardSession session = (StandardSession) sessions[i];
+        for (int i = 0; i < sortedSessions.length && toswap > 0; i++) {
+            StandardSession session = (StandardSession) 
sortedSessions[i].session();
             synchronized (session) {
                 int timeIdle = (int) (session.getIdleTimeInternal() / 1000L);
                 if (timeIdle >= minIdleSwap) {
@@ -833,7 +838,6 @@ public abstract class PersistentManagerBase extends 
ManagerBase implements Store
                 }
             }
         }
-
     }
 
 
@@ -877,6 +881,5 @@ public abstract class PersistentManagerBase extends 
ManagerBase implements Store
             }
         }
     }
-
 }
 
diff --git a/java/org/apache/catalina/session/SortableSession.java 
b/java/org/apache/catalina/session/SortableSession.java
new file mode 100644
index 0000000000..0e876e442a
--- /dev/null
+++ b/java/org/apache/catalina/session/SortableSession.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.session;
+
+import org.apache.catalina.Session;
+
+public record SortableSession(long timestamp, Session session) implements 
Comparable<SortableSession> {
+    @Override
+    public int compareTo(SortableSession o) {
+        return Long.compare(timestamp, o.timestamp);
+    }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to