https://bz.apache.org/bugzilla/show_bug.cgi?id=63210
Bug ID: 63210 Summary: Tomcat failing to shutdown if EvictionTimer thread is running Product: Tomcat 9 Version: 9.0.x Hardware: PC OS: Mac OS X 10.1 Status: NEW Severity: normal Priority: P2 Component: Catalina Assignee: dev@tomcat.apache.org Reporter: k...@gameldar.com Target Milestone: ----- Created attachment 36463 --> https://bz.apache.org/bugzilla/attachment.cgi?id=36463&action=edit stacktrace showing servlet initialization in 8.0.53 If a query is executed against a DataSource during the Servlet init phase when timeBetweenEvictionRunsMillis is defined on the DataSource when you try and shutdown Tomcat it will shutdown everything but the commons-pool-evictor-thread is left waiting and will not shut down (regardless of the value set in the timeBetweenEvictionRunsMillis). I found this issue as part of upgrading a webapp from working with Tomcat 8.0.53 to 9.0.16. It is caused by a change of behaviour between the two versions due to initialization of the Servlets happening in a different way between the two versions, namely that the Servlet initialization in Tomcat 8.0.53 happens in a separate thread, whereas with 9.0.x it happens on the main thread. This means that when the EvictionTimer thread is started it inherits the daemon flag from the parent thread (as it isn't explicitly set) which is false in 9.0.x and true in 8.0.53 and therefore when the main thread exits after shutdown in 9.0.x the common-pool-evictor-thread continues and stops termination of Tomcat. There is a workaround for this - by manually closing the underlying datasource during the Servlet destroy method. There are potentially two issues here: 1. The EvictionTimer thread should be marked as setDaemon after it is created (in the EvictorTimerFactory) this way it'll be killed when Tomcat is shutdown. See the attached diff which I've confirmed fixes the issue. 2. The resources are not actually being closed if they are loaded via a reference in the context. #2 here is perhaps the bigger issue - this may be an issue for more than just the EvictionTimer, but it was the one I hit. Full Replication steps: 1. Put the attached test.war into the base tomcat direct This war file was a simple webapp based upon: https://www.journaldev.com/2513/tomcat-datasource-jndi-example-java You'll need to create the database with the tables as described in that example. For reference I was using PostgreSQL. I've modified the source of the servlet however as attached (TestServlet.java) - namely it is now loading the JNDI DataSource during the Servlet.init() method and executing the same getEmployees query in the init method to ensure datasource pool initialized at that point. 2. create the context for the webapp - put the attached test.xml into conf/Catalina/localhost/test.xml. Note this is using a Resource for the DataSource and setting the timeBetweenEvictionRunsMillis="60000". You'll need to change the database configuration (url, driverClassname) in the Resource to point to your database. 3. Create the database and populate the tables (see the attached link) 4. Start up Tomcat using bin/start.sh 5. Connect to http://localhost:8080/test/ to confirm the servlet is loaded and working 6. Shutdown Tomcat using bin/shutdown.sh It'll say it is shutdown - and to ensure that it isn't stuck in the eviction wait time wait at least 60 seconds - but if you look at your processes you'll see the Tomcat instance is still running with a similar list of threads as seen in the attached jstack.log. The Servlet is producing the stacktrace during the init that shows the difference between the 9.0.x startup and the 8.0.53 startup (full stack traces are attached). 8.0.53 startup looks like: 26-Feb-2019 10:26:18.071 INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log java.lang.Exception at test.TestServlet.init(TestServlet.java:28) at javax.servlet.GenericServlet.init(GenericServlet.java:158) at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:118 // snip at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834) Whereas the 9.0.16 stacktrace traces back to the Bootstrap main method: Feb. 26, 2019 8:42:08 AM org.apache.catalina.core.ApplicationContext log INFO: java.lang.Exception at test.TestServlet.init(TestServlet.java:28) at javax.servlet.GenericServlet.init(GenericServlet.java:158) at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1123) // snip at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:350) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:492) -- You are receiving this mail because: You are the assignee for the bug. --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org