The latest version of Jenkins core uses Jetty 9.4, this version seems changes the way to manage the session cache and now it is infinite by default, this makes that the session cache is not cleaned with the time and cause a memory leak.

      This script gets the EvictionPolicy value and returns -1

      import net.bull.javamelody.* 
      def sessionMapField = SessionListener.class.getDeclaredField('SESSION_MAP_BY_ID') 
      sessionMapField.setAccessible(true) 
      def sessions = sessionMapField.get(null) 
      for (def sessionKV : sessions) { 
      def session = sessionKV.value 
        println session.getSessionHandler().getSessionCache().getEvictionPolicy() 
      }
      

      Jetty was upgraded from 9.2 to 9.4 in Jenkins 2.61, The old Jetty uses a different caching mechanism, which seems to have a non-infinite default eviction policy

      The workaround is to place this script at JENKINS_HOME/init.groovy.d to set the eviction policy to 30 min.

      import net.bull.javamelody.* 
      def sessionMapField = SessionListener.class.getDeclaredField('SESSION_MAP_BY_ID') 
      sessionMapField.setAccessible(true) 
      def sessions = sessionMapField.get(null) 
      for (def sessionKV : sessions) { 
      def session = sessionKV.value 
         session.getSessionHandler().getSessionCache().setEvictionPolicy(1800) 
      }
      

      These are other utility scripts to check the leak.

      This script list the sessions

      import net.bull.javamelody.* 
      println SessionListener.getSessionCount() + " sessions:" 
      def sessioninfos = SessionListener.getAllSessionsInformations() 
      for (sessioninfo in sessioninfos) { 
        println sessioninfo 
      }
      

      This script returns the number of sessions in cache

      import net.bull.javamelody.*
      
      def sessionMapField = SessionListener.class.getDeclaredField('SESSION_MAP_BY_ID')
      sessionMapField.setAccessible(true)
      def sessions = sessionMapField.get(null)
      for (def sessionKV: sessions) {
        def session = sessionKV.value
        def sessionCache = session.getSessionHandler().getSessionCache()
        def sessionsField = sessionCache.class.getDeclaredField('_sessions')
        sessionsField.setAccessible(true)
        println sessionsField.get(sessionCache).size()
      }
      

      This script force to clear the session cache

      import net.bull.javamelody.*
        
      def sessionMapField = SessionListener.class.getDeclaredField('SESSION_MAP_BY_ID')
      sessionMapField.setAccessible(true)
      def sessions = sessionMapField.get(null)
      for (def sessionKV: sessions) {
        def session = sessionKV.value
        def sessionCache = session.getSessionHandler().getSessionCache()
        def sessionsField = sessionCache.class.getDeclaredField('_sessions')
        sessionsField.setAccessible(true)
        def sessionKeys = sessionsField.get(sessionCache).keys()
        for (def sessionKey: sessionKeys) {
          sessionCache.delete(sessionKey)
        }
      }
      

          [JENKINS-49596] User session memory leak

          Ivan Fernandez Calvo created issue -
          Ivan Fernandez Calvo made changes -
          Summary Original: Uses session leak New: User session memory leak

          Oleg Nenashev added a comment -

          https://github.com/jenkinsci/winstone/pull/44 pulls in newer relese of Jetty. Let's see what olamy responds about this ticket

          Oleg Nenashev added a comment - https://github.com/jenkinsci/winstone/pull/44 pulls in newer relese of Jetty. Let's see what olamy responds about this ticket
          Oleg Nenashev made changes -
          Remote Link New: This issue links to "https://github.com/jenkinsci/winstone/pull/44 (Web Link)" [ 20092 ]

          Olivier Lamy added a comment -

          yup good catch sounds something to change in winstone and sessionCache configuration.
          I have updated https://github.com/jenkinsci/winstone/pull/44

          Olivier Lamy added a comment - yup good catch sounds something to change in winstone and sessionCache configuration. I have updated https://github.com/jenkinsci/winstone/pull/44
          Oleg Nenashev made changes -
          Assignee New: Olivier Lamy [ olamy ]
          Oleg Nenashev made changes -
          Status Original: Open [ 1 ] New: In Progress [ 3 ]
          Oleg Nenashev made changes -
          Status Original: In Progress [ 3 ] New: In Review [ 10005 ]

          Code changed in jenkins
          User: olivier lamy
          Path:
          src/java/winstone/HostConfiguration.java
          src/java/winstone/cmdline/Option.java
          http://jenkins-ci.org/commit/winstone/12474923c40149530094823ecbe80ff2d7f6f216
          Log:
          JENKINS-49596 session cache is never cleaned

          Signed-off-by: olivier lamy <olamy@apache.org>

          SCM/JIRA link daemon added a comment - Code changed in jenkins User: olivier lamy Path: src/java/winstone/HostConfiguration.java src/java/winstone/cmdline/Option.java http://jenkins-ci.org/commit/winstone/12474923c40149530094823ecbe80ff2d7f6f216 Log: JENKINS-49596 session cache is never cleaned Signed-off-by: olivier lamy <olamy@apache.org>

          Oleg Nenashev added a comment -

          ifernandezcalvo olamy I would like to highlight that the integrated pull request is not backportable. So it won't get into 2.107.x unless we prepare a separate patch-release for that.

          My proposal would be to...
          1) Create a separate branch and backport the issue fix to the Winstone baseline with old Jetty
          2) Release that version and integrate it into the next weekly. Mark this issue for backporting
          3) After that release the current master baseline and integrate it into a later weekly release.

          Oleg Nenashev added a comment - ifernandezcalvo olamy I would like to highlight that the integrated pull request is not backportable. So it won't get into 2.107.x unless we prepare a separate patch-release for that. My proposal would be to... 1) Create a separate branch and backport the issue fix to the Winstone baseline with old Jetty 2) Release that version and integrate it into the next weekly. Mark this issue for backporting 3) After that release the current master baseline and integrate it into a later weekly release.

            olamy Olivier Lamy
            ifernandezcalvo Ivan Fernandez Calvo
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: