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]