2

We are in the process of migrating our application from Websphere to Tomcat. One thing I have noticed is that when I issue the shutdown.sh for Tomcat, the process still keeps running. Initially I thought the process would end itself in a minute or two, but even after 5 minutes I still see the process alive. So I have to kill the process using kill -9 and then go for a start.

While shutting down I do see a lot of errors getting thrown on the console like:

org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [some_application] appears to have started a thread named [Timer-0] but has failed to stop it.

The code consists of webapps which are made a mix of servlets, spring and a whole bunch of threads are started when the application boots up.

Is there something I can do configuration-wise that would take care of this? Or this needs some code-work to compensate for something that WebSphere provided out-of-the-box?

hell_storm2004
  • 145
  • 2
  • 11

2 Answers2

4

Issues like that is best handled from code.

Although you can use catalina.sh stop -force to terminate the Tomcat instance no matter what, the point here is that Tomcat thinks those threads are running for a reason, and terminating your threads might leave your application in an inconsistent state (if it is terminated halfway of writing something, for example).

If you know for a fact that no such thing could happen, use the -force switch when stopping Tomcat.

However, it is best to write the application to either mark the threads as daemons (by calling setDaemon(true) on the Thread instance), so they can be terminated whenever the VM exits, or (if the threads should not be killed at any time) register a shutdown hook by implementing ServletContextListener, and doing the shutdown chores in the contextDestroyed method. Here is a question on StackOverflow about installing a shutdown hook.

Lacek
  • 6,585
  • 22
  • 28
1

You application is probably leaving a bunch of non-daemon threads running, so it will never shut down.

The thread you mention in your question is a TimerThread and Tomcat knows how to shut those down (almost) safely. Just add clearReferencesStopTimerThreads="true" to your application context:

<?xml version="1.0" encoding="UTF-8"?>
<Context docBase="yourAppName"
         clearReferencesStopTimerThreads="true" />

However, as mentioned by Lacek, the proper way to deal with them is through a ServletContextListener or another mechanism to administer the Thread's lifecycle. Since you are using a Spring container I would add a TaskScheduler (<task:scheduler id="" pool-size="" />) to your ApplicationContext and inject it into every bean that needs scheduling a task. If your servlets need to schedule tasks, create a ScheduledExecutorService in a ServletContextListener and store a reference to it in the ServletContext.

PS: there is also a clearReferencesStopThreads attribute, but the description in Apache Tomcat Configuration Manual should give you a hint, when to use it:

If true, Tomcat attempts to terminate threads that have been started by the web application. Stopping threads is performed via the deprecated (for good reason) Thread.stop() method and is likely to result in instability. As such, enabling this should be viewed as an option of last resort in a development environment and is not recommended in a production environment. If not specified, the default value of false will be used. If this feature is enabled, web applications may take up to two seconds longer to stop as executor threads are given up to two seconds to stop gracefully before Thread.stop() is called on any remaining threads.

Piotr P. Karwasz
  • 5,292
  • 2
  • 9
  • 20
  • Sorry for the delay. I just read the posts (seems a bit overwhelming now!) and I will try to implement them and will surely post back. Thanks! – hell_storm2004 Jun 24 '20 at 07:10