You're asking two questions:
Question 1: Is calling System.exit() inside a Servlet's destroy() method to forcefully kill any non-daemon threads a good idea?
Calling System.exit() inside ANY servlet-related method is always 100% incorrect. Your code is not the only code running in the JVM - even if you are the only servlet running (the servlet container has resources it will need to cleanup when the JVM really exits.)
The correct way to handle this case is to clean up your threads in the destroy() method. This means starting them in a way that lets you gently stop them in a correct way. Here is an example (where MyThread is one of your threads, and extends ServletManagedThread):
public class MyServlet extends HttpServlet {
private List<ServletManagedThread> threads = new ArrayList<ServletManagedThread>();
// lots of irrelevant stuff left out for brevity
public void init() {
ServletManagedThread t = new MyThread();
threads.add(t);
t.start();
}
public void destroy() {
for(ServletManagedThread thread : threads) {
thread.stopExecuting();
}
}
}
public abstract class ServletManagedThread extends Thread {
private boolean keepGoing = true;
protected abstract void doSomeStuff();
protected abstract void probablySleepForABit();
protected abstract void cleanup();
public void stopExecuting() {
keepRunning = false;
}
public void run() {
while(keepGoing) {
doSomeStuff();
probablySleepForABit();
}
this.cleanup();
}
}
It's also worth noting that there are thread/concurrency libraries out there that can help with this - but if you really do have a handful of threads that are started at servlet initialization and should run until the servlet is destroyed, this is probably all you need.
Question 2: Why does Tomcat 5.0.30 and (later versions including Tomcat 6.x.x) fail to shutdown properly if there's a System.exit() in the destroy() method of the Servlet?
Without more analysis, it's hard to know for certain. Microsoft says that Error 1053 occurs when Windows asks a service to shutdown, but the request times out. That would make it seem like something happened internally to Tomcat that got it into a really bad state. I would certainly suspect that your call to System.exit(
) could be the culprit. Tomcat (specifically, Catalina) does register a shutdown hook with the VM (see org.apache.catalina.startup.Catalina.start()
, at least in 5.0.30). That shutdown hook would get called by the JVM when you call System.exit()
. The shutdown hook delegates to the running services, so each service could potentially be required to do alot of work.
If the shutdown hooks (triggered by your System.exit()
) fail to execute (they deadlock or something like that,) then it is very easy to understand why the Error 1053 occurs, given the documentation of the Runtime.exit(int)
method (which is called from System.exit()
):
If this method is invoked after the
virtual machine has begun its shutdown
sequence then if shutdown hooks are
being run this method will block
indefinitely. If shutdown hooks have
already been run and on-exit
finalization has been enabled then
this method halts the virtual machine
with the given status code if the
status is nonzero; otherwise, it
blocks indefinitely.
This "indefinite blocking" behavior would definitely cause an Error 1053.
If you want a more complete answer than this, you can download the source and debug it yourself.
But, I would be willing to bet that if you properly handle your thread management issue (as outlined above,) your problems will go away.
In short, leave the System.exit() call to Tomcat - that's not your job.