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

lukaszlenart pushed a commit to branch feature/WW-3576-session-map-staleness
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 499415ea2c467cb3922e821874a9dbff67594345
Author: Lukasz Lenart <[email protected]>
AuthorDate: Sun Oct 18 08:59:09 2026 +0200

    WW-3576 fix(core): keep the pinned session in a local in SessionMap.put and 
harden the race test
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 core/src/main/java/org/apache/struts2/dispatcher/SessionMap.java   | 7 ++++---
 .../test/java/org/apache/struts2/dispatcher/SessionMapTest.java    | 7 +++++--
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/core/src/main/java/org/apache/struts2/dispatcher/SessionMap.java 
b/core/src/main/java/org/apache/struts2/dispatcher/SessionMap.java
index 54318391b..07b1ddffd 100644
--- a/core/src/main/java/org/apache/struts2/dispatcher/SessionMap.java
+++ b/core/src/main/java/org/apache/struts2/dispatcher/SessionMap.java
@@ -157,10 +157,11 @@ public class SessionMap extends AbstractMap<String, 
Object> implements Serializa
         HttpSession current = session;
         if (current == null) {
             synchronized (this) {
-                if (session == null) {
-                    session = request.getSession(true);
-                }
                 current = session;
+                if (current == null) {
+                    current = request.getSession(true);
+                    session = current;
+                }
             }
         }
 
diff --git 
a/core/src/test/java/org/apache/struts2/dispatcher/SessionMapTest.java 
b/core/src/test/java/org/apache/struts2/dispatcher/SessionMapTest.java
index 3edc9c380..5a602ebad 100644
--- a/core/src/test/java/org/apache/struts2/dispatcher/SessionMapTest.java
+++ b/core/src/test/java/org/apache/struts2/dispatcher/SessionMapTest.java
@@ -296,12 +296,13 @@ public class SessionMapTest extends TestCase {
         request.setSession(session);
         SessionMap sessionMap = new SessionMap(request);
         AtomicReference<Throwable> failure = new AtomicReference<>();
+        AtomicReference<Object> read = new AtomicReference<>();
 
         Thread invalidator = new Thread(sessionMap::invalidate);
         invalidator.start();
         invalidating.await();
         Thread reader = new Thread(() -> {
-            try { sessionMap.get("key"); } catch (Throwable t) { 
failure.set(t); }
+            try { read.set(sessionMap.get("key")); } catch (Throwable t) { 
failure.set(t); }
         });
         reader.start();
         long deadline = System.currentTimeMillis() + 5000;
@@ -313,7 +314,9 @@ public class SessionMapTest extends TestCase {
         invalidator.join(5000);
         reader.join(5000);
 
-        assertNull("get() concurrent with invalidate() threw", failure.get());
+        assertFalse("reader did not finish", reader.isAlive());
+        assertNull("get() concurrent with invalidate() threw: " + 
failure.get(), failure.get());
+        assertEquals("value", read.get());
     }
 
     @Override

Reply via email to