Program: 28765
Project: 28765
Buggy source:
/** 
 * Perform the internal processing required to invalidate this session, without triggering an exception if the session has already expired.
 * @param notify Should we notify listeners about the demise ofthis session?
 * @param persistentRemove should we call store to remove the sessionif available
 */
public void expire(boolean notify,boolean persistentRemove){
  if (expiring)   return;
synchronized (this) {
    if (manager == null)     return;
    expiring=true;
    List<HttpSessionListener> listeners=context.getSessionListeners();
    if (notify && !listeners.isEmpty()) {
      HttpSessionEvent event=new HttpSessionEvent(getSession());
      int len=listeners.size();
      for (int i=0; i < len; i++) {
        HttpSessionListener listener=listeners.get((len - 1) - i);
        try {
          fireContainerEvent(context,"String_Node_Str",listener);
          listener.sessionDestroyed(event);
          fireContainerEvent(context,"String_Node_Str",listener);
        }
 catch (        Throwable t) {
          try {
            fireContainerEvent(context,"String_Node_Str",listener);
          }
 catch (          Exception e) {
          }
          log(rb.getString(SESSION_EVENT_LISTENER_EXCEPTION),t);
        }
      }
    }
    setValid(false);
    long timeNow=System.currentTimeMillis();
    int timeAlive=(int)((timeNow - creationTime) / 1000);
synchronized (manager) {
      if (timeAlive > manager.getSessionMaxAliveTimeSeconds()) {
        manager.setSessionMaxAliveTimeSeconds(timeAlive);
      }
      int numExpired=manager.getExpiredSessions();
      numExpired++;
      manager.setExpiredSessions(numExpired);
      int average=manager.getSessionAverageAliveTimeSeconds();
      average=((average * (numExpired - 1)) + timeAlive) / numExpired;
      manager.setSessionAverageAliveTimeSeconds(average);
    }
    if (persistentRemove) {
      manager.remove(this);
    }
 else {
      if (manager instanceof PersistentManagerBase) {
        ((PersistentManagerBase)manager).remove(this,false);
      }
    }
    expiring=false;
    String keys[]=keys();
    for (int i=0; i < keys.length; i++)     removeAttribute(keys[i],notify,false);
    if (notify) {
      context.sessionExpiredEvent(this);
      fireSessionEvent(Session.SESSION_DESTROYED_EVENT,null);
    }
  }
}

Fixed version (ground truth):
/** 
 * Perform the internal processing required to invalidate this session, without triggering an exception if the session has already expired.
 * @param notify Should we notify listeners about the demise ofthis session?
 * @param persistentRemove should we call store to remove the sessionif available
 */
public void expire(boolean notify,boolean persistentRemove){
  if (expiring)   return;
synchronized (this) {
    if (manager == null)     return;
    expiring=true;
    ClassLoader oldTccl=null;
    if (context.getLoader() != null && context.getLoader().getClassLoader() != null) {
      oldTccl=Thread.currentThread().getContextClassLoader();
      if (Globals.IS_SECURITY_ENABLED) {
        PrivilegedAction<Void> pa=new PrivilegedSetTccl(context.getLoader().getClassLoader());
        AccessController.doPrivileged(pa);
      }
 else {
        Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());
      }
    }
    try {
      List<HttpSessionListener> listeners=context.getSessionListeners();
      if (notify && !listeners.isEmpty()) {
        HttpSessionEvent event=new HttpSessionEvent(getSession());
        int len=listeners.size();
        for (int i=0; i < len; i++) {
          HttpSessionListener listener=listeners.get((len - 1) - i);
          try {
            fireContainerEvent(context,"String_Node_Str",listener);
            listener.sessionDestroyed(event);
            fireContainerEvent(context,"String_Node_Str",listener);
          }
 catch (          Throwable t) {
            try {
              fireContainerEvent(context,"String_Node_Str",listener);
            }
 catch (            Exception e) {
            }
            log(rb.getString(SESSION_EVENT_LISTENER_EXCEPTION),t);
          }
        }
      }
    }
  finally {
      if (oldTccl != null) {
        if (Globals.IS_SECURITY_ENABLED) {
          PrivilegedAction<Void> pa=new PrivilegedSetTccl(oldTccl);
          AccessController.doPrivileged(pa);
        }
 else {
          Thread.currentThread().setContextClassLoader(oldTccl);
        }
      }
    }
    setValid(false);
    long timeNow=System.currentTimeMillis();
    int timeAlive=(int)((timeNow - creationTime) / 1000);
synchronized (manager) {
      if (timeAlive > manager.getSessionMaxAliveTimeSeconds()) {
        manager.setSessionMaxAliveTimeSeconds(timeAlive);
      }
      int numExpired=manager.getExpiredSessions();
      numExpired++;
      manager.setExpiredSessions(numExpired);
      int average=manager.getSessionAverageAliveTimeSeconds();
      average=((average * (numExpired - 1)) + timeAlive) / numExpired;
      manager.setSessionAverageAliveTimeSeconds(average);
    }
    if (persistentRemove) {
      manager.remove(this);
    }
 else {
      if (manager instanceof PersistentManagerBase) {
        ((PersistentManagerBase)manager).remove(this,false);
      }
    }
    expiring=false;
    String keys[]=keys();
    for (int i=0; i < keys.length; i++)     removeAttribute(keys[i],notify,false);
    if (notify) {
      context.sessionExpiredEvent(this);
      fireSessionEvent(Session.SESSION_DESTROYED_EVENT,null);
    }
  }
}