Grails
  1. Grails
  2. GRAILS-2544

Stopping Tomcat Context and doing undeploy does not completely shut down app, grails jars still locked

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.0.1
    • Fix Version/s: 1.2-M3
    • Component/s: Project infrastructure
    • Labels:
      None
    • Environment:
      Grails 1.0.1 - Windows - Tomcat 6

      Description

      Hi,
      We have a grails app that is being tested on tomcat 6.

      We have a META-INF/context.xml defined in our WAR file. We start tomcat and deploy this WAR via the manager interface to the root context. The WAR is deployed OK and the app runs great. We then go into the tomcat manager and do a "STOP" on the context.

      Noticed this output in the tomcat STDOUT
      log4j:ERROR LogMananger.repositorySelector was null likely due to error in class reloading, using NOPLoggerRepository.

      Secondly, we then do a tomcat "undeploy" which deletes all the deployed context files. When this is completed, the following Grails jars are left in the <contextRoot>/WEB-INF/lib directory. Because of this you cannot re-deploy your WAR again unless you kill the entire tomcat process to delete the jars. Maybe something in grails' ServletContextListener is not properly handling a shutdown and releasing resources?

      grails-cli-1.0.1.jar
      *-core.1.0.1.jar
      *-crud-1.0.1.jar
      *-gorm-1.0.1.jar
      *-spring-1.0.1.jar
      *-web-1.0.1.jar
      *-webflow-1.0.1.jar

        Issue Links

          Activity

          Hide
          John Allison added a comment -

          Here's a log4j mailing list post that might be about this. The reference bugs and the bugs they reference might be the problem, i.e. not particularly a grails bug? HTH

          http://marc.info/?l=log4j-user&m=120897082320333&w=2

          Show
          John Allison added a comment - Here's a log4j mailing list post that might be about this. The reference bugs and the bugs they reference might be the problem, i.e. not particularly a grails bug? HTH http://marc.info/?l=log4j-user&m=120897082320333&w=2
          Hide
          Lari Hotari added a comment -

          Hi,

          I wonder if these tips help:

          "Memory leaks where the classloader cannot be garbage collected"
          http://opensource.atlassian.com/confluence/spring/pages/viewpage.action?pageId=2669

          Two pointers from this article:
          http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/web/util/IntrospectorCleanupListener.html
          (cleans JavaBeans Intropector cache, might not be required on Java 1.5.0)

          There's a solution for freeing references to JDBC drivers loaded from the webapp's classloader:

          // code written by Guillaume Poirier
          public class CleanupListener implements ServletContextListener { 
            public void contextInitialized(ServletContextEvent event) { 
            } 
            public void contextDestroyed(ServletContextEvent event) { 
              try { 
                Introspector.flushCaches(); 
                for (Enumeration e = DriverManager.getDrivers(); e.hasMoreElements();) { 
                  Driver driver = (Driver) e.nextElement(); 
                  if (driver.getClass().getClassLoader() == getClass().getClassLoader()) { 
                    DriverManager.deregisterDriver(driver);          
                  } 
                } 
              } catch (Throwable e) { 
                System.err.println("Failled to cleanup ClassLoader for webapp"); 
                e.printStackTrace(); 
              } 
            } 
          }
          

          (code written by Guillaume Poirier)

          I think Grails needs the DriverManager.deregisterDriver solution since JDBC drivers are commonly loaded from the webapp classloader.

          Show
          Lari Hotari added a comment - Hi, I wonder if these tips help: "Memory leaks where the classloader cannot be garbage collected" http://opensource.atlassian.com/confluence/spring/pages/viewpage.action?pageId=2669 Two pointers from this article: http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/web/util/IntrospectorCleanupListener.html (cleans JavaBeans Intropector cache, might not be required on Java 1.5.0) There's a solution for freeing references to JDBC drivers loaded from the webapp's classloader: // code written by Guillaume Poirier public class CleanupListener implements ServletContextListener { public void contextInitialized(ServletContextEvent event) { } public void contextDestroyed(ServletContextEvent event) { try { Introspector.flushCaches(); for (Enumeration e = DriverManager.getDrivers(); e.hasMoreElements();) { Driver driver = (Driver) e.nextElement(); if (driver.getClass().getClassLoader() == getClass().getClassLoader()) { DriverManager.deregisterDriver(driver); } } } catch (Throwable e) { System .err.println( "Failled to cleanup ClassLoader for webapp" ); e.printStackTrace(); } } } (code written by Guillaume Poirier) I think Grails needs the DriverManager.deregisterDriver solution since JDBC drivers are commonly loaded from the webapp classloader.
          Hide
          Mark Thomas added a comment -

          I have done some analysis with YourKit and Grails running on Tomcat. Grails does indeed need to clean up its JDBC drivers. Note that the classloader test in the code example above is unnecessary since DriverManager.getDrivers() will only return the Driver instances loaded by the webapp.

          Grails uses ThreadLocals in org.codehaus.groovy.grails.documentation.DocumentationContext. These also need to be cleaned up. As a general rule for webapps, a ThreadLocal should not exist beyond the life of a individual request else memory leaks will follow.

          Finally, there is a log4j bug that I discovered (not yet reported) where loading a config file from a jar will lock the jar. The workaround is to place your log4j config file in WEB-INF/classes, rather than inside a JAR in WEB-INF/lib

          As an aside, I fixed Tomcat's JDBC driver clean-up code and I have some really ugly ThreadLocal clean-up code that I'll commit to Tomcat trunk once I have a chance to clean it up.

          Show
          Mark Thomas added a comment - I have done some analysis with YourKit and Grails running on Tomcat. Grails does indeed need to clean up its JDBC drivers. Note that the classloader test in the code example above is unnecessary since DriverManager.getDrivers() will only return the Driver instances loaded by the webapp. Grails uses ThreadLocals in org.codehaus.groovy.grails.documentation.DocumentationContext. These also need to be cleaned up. As a general rule for webapps, a ThreadLocal should not exist beyond the life of a individual request else memory leaks will follow. Finally, there is a log4j bug that I discovered (not yet reported) where loading a config file from a jar will lock the jar. The workaround is to place your log4j config file in WEB-INF/classes, rather than inside a JAR in WEB-INF/lib As an aside, I fixed Tomcat's JDBC driver clean-up code and I have some really ugly ThreadLocal clean-up code that I'll commit to Tomcat trunk once I have a chance to clean it up.
          Hide
          Graeme Rocher added a comment -

          I have implemented the DriverManager change, cleaned up the ThreadLocal code that we have in Grails, and removed the log4j.properties file from the WAR deployment. Hopefully, with the next Grails 1.2 milestone and Tomcat release this issue can be closed.

          Show
          Graeme Rocher added a comment - I have implemented the DriverManager change, cleaned up the ThreadLocal code that we have in Grails, and removed the log4j.properties file from the WAR deployment. Hopefully, with the next Grails 1.2 milestone and Tomcat release this issue can be closed.
          Hide
          Graeme Rocher added a comment -

          Tested against Grails 1.2 SNAPSHOT and Tomcat 6.0.20 with -Dorg.apache.catalina.loader.WebappClassLoader.ENABLE_CLEAR_REFERENCES=false and no errors occur on undeployment

          closing issue

          Show
          Graeme Rocher added a comment - Tested against Grails 1.2 SNAPSHOT and Tomcat 6.0.20 with -Dorg.apache.catalina.loader.WebappClassLoader.ENABLE_CLEAR_REFERENCES=false and no errors occur on undeployment closing issue

            People

            • Assignee:
              Graeme Rocher
              Reporter:
              InterZ
            • Votes:
              20 Vote for this issue
              Watchers:
              21 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development