Author: markt Date: Thu May 1 14:11:26 2008 New Revision: 652662 URL: http://svn.apache.org/viewvc?rev=652662&view=rev Log: Fix bug 43343. Correctly handle the case where a request arrives for a session we are in the middle of persisting.
Modified: tomcat/trunk/java/org/apache/catalina/session/PersistentManagerBase.java tomcat/trunk/java/org/apache/catalina/valves/PersistentValve.java Modified: tomcat/trunk/java/org/apache/catalina/session/PersistentManagerBase.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/session/PersistentManagerBase.java?rev=652662&r1=652661&r2=652662&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/session/PersistentManagerBase.java (original) +++ tomcat/trunk/java/org/apache/catalina/session/PersistentManagerBase.java Thu May 1 14:11:26 2008 @@ -590,6 +590,23 @@ public Session findSession(String id) throws IOException { Session session = super.findSession(id); + // OK, at this point, we're not sure if another thread is trying to + // remove the session or not so the only way around this is to lock it + // (or attempt to) and then try to get it by this session id again. If + // the other code ran swapOut, then we should get a null back during + // this run, and if not, we lock it out so we can access the session + // safely. + if(session != null) { + synchronized(session){ + session = super.findSession(session.getIdInternal()); + if(session != null){ + // To keep any external calling code from messing up the + // concurrency. + session.access(); + session.endAccess(); + } + } + } if (session != null) return (session); @@ -1024,24 +1041,24 @@ long timeNow = System.currentTimeMillis(); // Swap out all sessions idle longer than maxIdleSwap - // FIXME: What's preventing us from mangling a session during - // a request? if (maxIdleSwap >= 0) { for (int i = 0; i < sessions.length; i++) { StandardSession session = (StandardSession) sessions[i]; - if (!session.isValid()) - continue; - int timeIdle = // Truncate, do not round up - (int) ((timeNow - session.getLastAccessedTime()) / 1000L); - if (timeIdle > maxIdleSwap && timeIdle > minIdleSwap) { - if (log.isDebugEnabled()) - log.debug(sm.getString - ("persistentManager.swapMaxIdle", - session.getIdInternal(), new Integer(timeIdle))); - try { - swapOut(session); - } catch (IOException e) { - ; // This is logged in writeSession() + synchronized (session) { + if (!session.isValid()) + continue; + int timeIdle = // Truncate, do not round up + (int) ((timeNow - session.getLastAccessedTime()) / 1000L); + if (timeIdle > maxIdleSwap && timeIdle > minIdleSwap) { + if (log.isDebugEnabled()) + log.debug(sm.getString + ("persistentManager.swapMaxIdle", + session.getIdInternal(), new Integer(timeIdle))); + try { + swapOut(session); + } catch (IOException e) { + ; // This is logged in writeSession() + } } } } @@ -1073,19 +1090,21 @@ long timeNow = System.currentTimeMillis(); for (int i = 0; i < sessions.length && toswap > 0; i++) { - int timeIdle = // Truncate, do not round up - (int) ((timeNow - sessions[i].getLastAccessedTime()) / 1000L); - if (timeIdle > minIdleSwap) { - if(log.isDebugEnabled()) - log.debug(sm.getString - ("persistentManager.swapTooManyActive", - sessions[i].getIdInternal(), new Integer(timeIdle))); - try { - swapOut(sessions[i]); - } catch (IOException e) { - ; // This is logged in writeSession() + synchronized (sessions[i]) { + int timeIdle = // Truncate, do not round up + (int) ((timeNow - sessions[i].getLastAccessedTime()) / 1000L); + if (timeIdle > minIdleSwap) { + if(log.isDebugEnabled()) + log.debug(sm.getString + ("persistentManager.swapTooManyActive", + sessions[i].getIdInternal(), new Integer(timeIdle))); + try { + swapOut(sessions[i]); + } catch (IOException e) { + ; // This is logged in writeSession() + } + toswap--; } - toswap--; } } @@ -1107,20 +1126,22 @@ if (maxIdleBackup >= 0) { for (int i = 0; i < sessions.length; i++) { StandardSession session = (StandardSession) sessions[i]; - if (!session.isValid()) - continue; - int timeIdle = // Truncate, do not round up - (int) ((timeNow - session.getLastAccessedTime()) / 1000L); - if (timeIdle > maxIdleBackup) { - if (log.isDebugEnabled()) - log.debug(sm.getString - ("persistentManager.backupMaxIdle", - session.getIdInternal(), new Integer(timeIdle))); - - try { - writeSession(session); - } catch (IOException e) { - ; // This is logged in writeSession() + synchronized (session) { + if (!session.isValid()) + continue; + int timeIdle = // Truncate, do not round up + (int) ((timeNow - session.getLastAccessedTime()) / 1000L); + if (timeIdle > maxIdleBackup) { + if (log.isDebugEnabled()) + log.debug(sm.getString + ("persistentManager.backupMaxIdle", + session.getIdInternal(), new Integer(timeIdle))); + + try { + writeSession(session); + } catch (IOException e) { + ; // This is logged in writeSession() + } } } } Modified: tomcat/trunk/java/org/apache/catalina/valves/PersistentValve.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/PersistentValve.java?rev=652662&r1=652661&r2=652662&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/valves/PersistentValve.java (original) +++ tomcat/trunk/java/org/apache/catalina/valves/PersistentValve.java Thu May 1 14:11:26 2008 @@ -30,16 +30,18 @@ import org.apache.catalina.Store; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; -import org.apache.catalina.core.StandardHost; import org.apache.catalina.session.PersistentManager; import org.apache.catalina.util.StringManager; /** - * Valve that implements the default basic behavior for the - * <code>StandardHost</code> container implementation. + * Valve that implements per-request session persistence. It is intended to be + * used with non-sticky load-balancers. * <p> * <b>USAGE CONSTRAINT</b>: To work correctly it requires a PersistentManager. + * <p> + * <b>USAGE CONSTRAINT</b>: To work correctly it assumes only one request exists + * per session at any one time. * * @author Jean-Frederic Clere * @version $Revision$ $Date$ @@ -97,7 +99,6 @@ throws IOException, ServletException { // Select the Context to be used for this Request - StandardHost host = (StandardHost) getContainer(); Context context = request.getContext(); if (context == null) { response.sendError --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]