diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java index 14dce7f38cb..dc599cc5dc2 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java @@ -50,6 +50,12 @@ public class HashedSession extends AbstractSession * due to serialization failures that are most likely caused by user * data stored in the session that is not serializable. */ private transient boolean _saveFailed = false; + + /** + * True if an attempt has been made to de-idle a session and it failed. Once + * true, the session will not be attempted to be de-idled again. + */ + private transient boolean _deIdleFailed = false; /* ------------------------------------------------------------- */ protected HashedSession(HashSessionManager hashSessionManager, HttpServletRequest request) @@ -68,7 +74,7 @@ public class HashedSession extends AbstractSession /* ------------------------------------------------------------- */ protected void checkValid() { - if (_hashSessionManager._idleSavePeriodMs!=0) + if (!_deIdleFailed && _hashSessionManager._idleSavePeriodMs!=0) deIdle(); super.checkValid(); } @@ -196,7 +202,7 @@ public class HashedSession extends AbstractSession /* ------------------------------------------------------------ */ public synchronized void deIdle() { - if (isIdled()) + if (isIdled() && !_deIdleFailed) { // Access now to prevent race with idling period access(System.currentTimeMillis()); @@ -225,6 +231,7 @@ public class HashedSession extends AbstractSession } catch (Exception e) { + deIdleFailed(); LOG.warn("Problem de-idling session " + super.getId(), e); if (fis != null) IO.close(fis);//Must ensure closed before invalidate invalidate(); @@ -265,4 +272,15 @@ public class HashedSession extends AbstractSession _saveFailed = true; } + /* ------------------------------------------------------------ */ + public synchronized void deIdleFailed() + { + _deIdleFailed = true; + } + + /* ------------------------------------------------------------ */ + public synchronized boolean isDeIdleFailed() + { + return _deIdleFailed; + } } diff --git a/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/IdleSessionTest.java b/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/IdleSessionTest.java index 20d3351e845..4bcfdd86bb7 100644 --- a/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/IdleSessionTest.java +++ b/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/IdleSessionTest.java @@ -38,6 +38,8 @@ import org.eclipse.jetty.server.SessionManager; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.StdErrLog; import org.junit.Test; @@ -49,6 +51,7 @@ import org.junit.Test; */ public class IdleSessionTest { + public class IdleHashTestServer extends HashTestServer { private int _idlePeriod; @@ -108,7 +111,8 @@ public class IdleSessionTest int inactivePeriod = 200; int scavengePeriod = 3; int idlePeriod = 5; - + ((StdErrLog)Log.getLogger(org.eclipse.jetty.server.session.HashedSession.class)).setHideStacks(true); + System.setProperty("org.eclipse.jetty.STACKS", "false"); File storeDir = new File (System.getProperty("java.io.tmpdir"), "idle-test"); storeDir.deleteOnExit(); @@ -135,10 +139,10 @@ public class IdleSessionTest sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); //and wait until the session should be idled out - pause(scavengePeriod * 2); + pause(idlePeriod * 2); //check that the file exists - checkSessionIdled(storeDir); + checkSessionIdled(storeDir, getSessionId(sessionCookie)); //make another request to de-idle the session Request request = client.newRequest(url + "?action=test"); @@ -149,6 +153,23 @@ public class IdleSessionTest //check session de-idled checkSessionDeIdled(storeDir); + //wait again for the session to be idled + pause(idlePeriod * 2); + + //check that it is + checkSessionIdled(storeDir, getSessionId(sessionCookie)); + + + //delete the file + File idleFile = getIdleFile(storeDir, getSessionId(sessionCookie)); + assertTrue(idleFile.exists()); + assertTrue(idleFile.delete()); + + //make a request + request = client.newRequest(url + "?action=testfail"); + request.getHeaders().add("Cookie", sessionCookie); + response2 = request.send(); + assertEquals(HttpServletResponse.SC_OK,response2.getStatus()); } finally { @@ -158,13 +179,14 @@ public class IdleSessionTest } - public void checkSessionIdled (File sessionDir) + public void checkSessionIdled (File sessionDir, String sessionId) { assertNotNull(sessionDir); assertTrue(sessionDir.exists()); String[] files = sessionDir.list(); assertNotNull(files); assertEquals(1, files.length); + assertEquals(sessionId, files[0]); } @@ -176,7 +198,23 @@ public class IdleSessionTest assertNotNull(files); assertEquals(0, files.length); } + + public File getIdleFile (File sessionDir, String sessionId) + { + assertNotNull(sessionDir); + assertTrue(sessionDir.exists()); + String[] files = sessionDir.list(); + assertNotNull(files); + return new File(sessionDir, files[0]); + } + public String getSessionId (String sessionCookie) + { + assertNotNull(sessionCookie); + String sessionId = sessionCookie.substring(11); + sessionId = sessionId.substring(0, sessionId.indexOf(';')); + return sessionId; + } public static class TestServlet extends HttpServlet { @@ -201,6 +239,11 @@ public class IdleSessionTest assertEquals("test", session.getAttribute("test")); assertTrue(!((HashedSession)session).isIdled()); } + else if ("testfail".equals(action)) + { + HttpSession session = request.getSession(false); + assertTrue(session == null); + } } } }