From 0f3167e5d20b23c1daaeec4dc2f4c685a2895ee4 Mon Sep 17 00:00:00 2001 From: markt Date: Wed, 17 Feb 2010 13:51:37 +0000 Subject: [PATCH] Improve logging behaviour when shutdown occurs via a shutdownhook. If present, use Catalina's shutdown hook to shutdown Tomcat and JULI. This enables them to be shutdown in the correct order. git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@910974 13f79535-47bb-0310-9956-ffa450edef68 --- java/org/apache/catalina/startup/Catalina.java | 18 +++++++ java/org/apache/juli/ClassLoaderLogManager.java | 71 ++++++++++++++++++------- 2 files changed, 70 insertions(+), 19 deletions(-) diff --git a/java/org/apache/catalina/startup/Catalina.java b/java/org/apache/catalina/startup/Catalina.java index a7c722a8c..4fd68491e 100644 --- a/java/org/apache/catalina/startup/Catalina.java +++ b/java/org/apache/catalina/startup/Catalina.java @@ -28,11 +28,13 @@ import java.net.Socket; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.logging.LogManager; import org.apache.catalina.Container; import org.apache.catalina.Lifecycle; import org.apache.catalina.LifecycleException; import org.apache.catalina.core.StandardServer; +import org.apache.juli.ClassLoaderLogManager; import org.apache.tomcat.util.digester.Digester; import org.apache.tomcat.util.digester.Rule; import org.xml.sax.Attributes; @@ -572,6 +574,15 @@ public class Catalina extends Embedded { shutdownHook = new CatalinaShutdownHook(); } Runtime.getRuntime().addShutdownHook(shutdownHook); + + // If JULI is being used, disable JULI's shutdown hook since + // shutdown hooks run in parallel and log messages may be lost + // if JULI's hook completes before the CatalinaShutdownHook() + LogManager logManager = LogManager.getLogManager(); + if (logManager instanceof ClassLoaderLogManager) { + ((ClassLoaderLogManager) logManager).setUseShutdownHook( + false); + } } } catch (Throwable t) { // This will fail on JDK 1.2. Ignoring, as Tomcat can run @@ -652,6 +663,13 @@ public class Catalina extends Embedded { Catalina.this.stop(); } + // If JULI is used, shut JULI down *after* the server shuts down + // so log messages aren't lost + LogManager logManager = LogManager.getLogManager(); + if (logManager instanceof ClassLoaderLogManager) { + ((ClassLoaderLogManager) logManager).shutdown(); + } + } } diff --git a/java/org/apache/juli/ClassLoaderLogManager.java b/java/org/apache/juli/ClassLoaderLogManager.java index 96ddf1725..ac6f14a97 100644 --- a/java/org/apache/juli/ClassLoaderLogManager.java +++ b/java/org/apache/juli/ClassLoaderLogManager.java @@ -50,25 +50,8 @@ public class ClassLoaderLogManager extends LogManager { @Override public void run() { - // The JVM us being shutdown. Make sure all loggers for all class - // loaders are shutdown - for (ClassLoaderLogInfo clLogInfo : classLoaderLoggers.values()) { - for (Logger logger : clLogInfo.loggers.values()) { - resetLogger(logger); - } - } - } - - private void resetLogger(Logger logger) { - - Handler[] handlers = logger.getHandlers(); - for (Handler handler : handlers) { - logger.removeHandler(handler); - try { - handler.close(); - } catch (Exception e) { - // Ignore - } + if (useShutdownHook) { + shutdown(); } } @@ -105,7 +88,29 @@ public class ClassLoaderLogManager extends LogManager { */ protected ThreadLocal prefix = new ThreadLocal(); + + /** + * Determines if the shutdown hook is used to perform any necessary + * clean-up such as flushing buffered handlers on JVM shutdown. Defaults to + * true but may be set to false if another component ensures + * that + */ + protected boolean useShutdownHook = true; + + // ------------------------------------------------------------- Properties + + + public boolean isUseShutdownHook() { + return useShutdownHook; + } + + + public void setUseShutdownHook(boolean useShutdownHook) { + this.useShutdownHook = useShutdownHook; + } + + // --------------------------------------------------------- Public Methods @@ -294,7 +299,35 @@ public class ClassLoaderLogManager extends LogManager { readConfiguration(is, Thread.currentThread().getContextClassLoader()); } + + + /** + * Shuts down the logging system. + */ + public void shutdown() { + // The JVM us being shutdown. Make sure all loggers for all class + // loaders are shutdown + for (ClassLoaderLogInfo clLogInfo : classLoaderLoggers.values()) { + for (Logger logger : clLogInfo.loggers.values()) { + resetLogger(logger); + } + } + } + + // -------------------------------------------------------- Private Methods + private void resetLogger(Logger logger) { + Handler[] handlers = logger.getHandlers(); + for (Handler handler : handlers) { + logger.removeHandler(handler); + try { + handler.close(); + } catch (Exception e) { + // Ignore + } + } + } + // ------------------------------------------------------ Protected Methods -- 2.11.0