andre John Mas wrote:
Hi,

We are currently experiencing session issues with our customer's Tomcat server, in a production environment. Basically what is happening is that, despite the idle time-out being set for 20 minutes we are seeing sessions that have been idle (have not been accessed) for over 3 hours. The net result is that the Tomcat server needs to get restarted.

We are currently investigating the reason why, but are currently in the dark on how we should continue our analysis. If anyone has any ideas they would be much appreciated.

There is a race condition when Tomcat 5.0 maintains the accessCount attribute of a session, see

   https://issues.apache.org/bugzilla/show_bug.cgi?id=37356
   Tomcat does not invalidate sessions after session-timeout period has
   passed.

This bug is fixed in Tomcat 5.5 and 6. We have seen it causing sessions to hang around forever in production servers.

Furthermore there is a concurrency bug accessing the session attributes:

   https://issues.apache.org/bugzilla/show_bug.cgi?id=36541
   session getAttribute/setAttribute and removeAttribute are NOT Thread
   safe.

Both are fixed in the patch below for Tomcat 5.0

Regards,

Oliver Schoett


--- 
dist/jakarta-tomcat-5.0.25-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/session/StandardSession.java
  2004-05-17 20:10:50.000000000 +0200
+++ 
jakarta-tomcat-5.0.25-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/session/StandardSession.java
       2008-09-25 14:53:15.046667200 +0200
@@ -31,6 +31,8 @@
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.Iterator;

 import javax.servlet.ServletContext;
@@ -116,7 +118,7 @@
     /**
      * The collection of user data attributes associated with this Session.
      */
-    protected HashMap attributes = new HashMap();
+    protected Map attributes = new ConcurrentHashMap();


     /**
@@ -280,6 +282,11 @@
      */
     protected transient int accessCount = 0;

+    /**
+     * Object used to synchronize accesses to accessCount
+     */
+    private final transient Object accessCountLock = new Object();
+

     // ----------------------------------------------------- Session Properties

@@ -555,8 +562,10 @@
             return false;
         }

-        if (accessCount>  0) {
-            return true;
+        synchronized (accessCountLock) {
+            if (accessCount>  0) {
+                return true;
+            }
         }

         if (maxInactiveInterval>= 0) {
@@ -597,7 +606,9 @@

         evaluateIfValid();

-        accessCount++;
+        synchronized (accessCountLock) {
+            accessCount++;
+        }

     }

@@ -608,7 +619,9 @@
     public void endAccess() {

         isNew = false;
-        accessCount--;
+        synchronized (accessCountLock) {
+            accessCount--;
+        }

     }

@@ -687,7 +700,9 @@
                     }
                 }
             }
-            accessCount = 0;
+            synchronized (accessCountLock) {
+                accessCount = 0;
+            }
             setValid(false);

             // Remove this session from our manager's active sessions
@@ -802,7 +817,9 @@
         id = null;
         lastAccessedTime = 0L;
         maxInactiveInterval = -1;
-        accessCount = 0;
+        synchronized (accessCountLock) {
+            accessCount = 0;
+        }
         notes.clear();
         setPrincipal(null);
         isNew = false;
@@ -1329,7 +1346,7 @@

         // Deserialize the attribute count and attribute values
         if (attributes == null)
-            attributes = new HashMap();
+            attributes = new ConcurrentHashMap();
         int n = ((Integer) stream.readObject()).intValue();
         boolean isValidSave = isValid;
         isValid = true;
@@ -1341,9 +1358,9 @@
             if (debug>= 2)
                 log("  loading attribute '" + name +
                     "' with value '" + value + "'");
-            synchronized (attributes) {
+            // OS no longer needed: synchronized (attributes) {
                 attributes.put(name, value);
-            }
+            // OS no longer needed: }
         }
         isValid = isValidSave;

@@ -1388,9 +1405,9 @@
         ArrayList saveValues = new ArrayList();
         for (int i = 0; i<  keys.length; i++) {
             Object value = null;
-            synchronized (attributes) {
+            // OS no longer needed: synchronized (attributes) {
                 value = attributes.get(keys[i]);
-            }
+            // OS no longer needed: }
             if (value == null)
                 continue;
             else if ( (value instanceof Serializable)




---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to