tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bugzi...@apache.org
Subject DO NOT REPLY [Bug 46085] New: Session are incorrectly expired due to thread unsafe code
Date Fri, 24 Oct 2008 19:53:11 GMT
https://issues.apache.org/bugzilla/show_bug.cgi?id=46085

           Summary: Session are incorrectly expired due to thread unsafe
                    code
           Product: Tomcat 6
           Version: 6.0.18
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: major
          Priority: P2
         Component: Catalina
        AssignedTo: dev@tomcat.apache.org
        ReportedBy: pms52@cam.ac.uk


We have identified a bug where sessions are expired even though they are still
valid.  

The source of the problem is concurrent threads reading and writing
thisAccessTime in "org.apache.catalina.session.StandardSession" in a way that
is not thread safe. 

The good news is that we have a simple solution, for Tomcat 6.  The fix is to
mark the class level variables - thisAccessedTime and lastAccessedTime - as
volatile.



Detailed explanation of the bug:

We found that StandardSession's isValid() function was making a call to
expire() on the following block of code:

        if (maxInactiveInterval >= 0) { 
            long timeNow = System.currentTimeMillis();
            int timeIdle = (int) ((timeNow - thisAccessedTime) / 1000L);
            if (timeIdle >= maxInactiveInterval) {
                expire(true);
            }
        }

Debugging showed that thisAccessedTime was in the past (1983!) and therefore
timeIdle is large enough for expiry to happen.

In another thread running in parallel, the access() function runs this line of
code:

    this.thisAccessedTime = System.currentTimeMillis();

That single line of code might be atomic, i.e. is composed of multiple
instructions, which means it is possible for another thread reading
thisAccessedTime to read a value that is effectively corrupt.  Marking
thisAccessedTime as volatile ensures that writes are completely finished before
reading is allowed. 

Note that the volatile solution only works for Java 1.5 or higher as the
meaning of volatile changed then. That means it cannot be used for older
Tomcat's if they have a similar problem. Another solution would have been to
synchronize reads and writes to that variable.



Reproducing the bug:

This is quite hard within Tomcat as is very dependant on timings, the JVM's
optimisations, and any changes to code may affect optimisations. We are only
able to reproduce the bug on multiprocessor systems running an IBM JVM.

Specifically, we are running:
  SLES 10.3 Linux on an Intel platform.
  Two or more Intel CPU's
  Tomcat 6.0.18
  JVM package: java-1_5_0-ibm-1.5.0_sr8 ( https://svn.apache.org/viewcvs.cgi?view=rev&rev=8
)a-1.1

Initially, we thought that System.currentTimeMillis() was returning an
incorrect value and created a test program which demo'd the problem to IBM.  We
were wrong but they did give us the volatile solution.  See here:
http://www.ibm.com/developerworks/forums/thread.jspa?threadID=230478


-- 
Configure bugmail: https://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Mime
View raw message