Repository: logging-log4j2
Updated Branches:
  refs/heads/master 95cc02a51 -> 19832cf09


[LOG4J2-1259] Log4j threads are leaking on Tomcat shutdown.

Use the LifeCycle2.stop(long, TimeUnit) API to shutdown Log4j in the Web
module. Before this code, I am thinking that when the container shuts
down log4j and unloads the classes, some Log4j  code is left running and
causes problems like "Could not load
org.apache.logging.log4j.core.config.ConfiguratonFileWatcher$ReconfigurationWorker."
described in
https://issues.apache.org/jira/browse/LOG4J2-1259?focusedCommentId=15510324&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-15510324
This commit adds two servlet init parameters called "log4j.stop.timeout"
and "log4j.stop.timeout.timeunit" with defaults of 30 and
TimeUnit.SECONDS.

Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/19832cf0
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/19832cf0
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/19832cf0

Branch: refs/heads/master
Commit: 19832cf09962a73d1f3541c42719f9d9da1f41e8
Parents: 95cc02a
Author: Gary Gregory <ggreg...@apache.org>
Authored: Wed Sep 21 11:01:32 2016 -0700
Committer: Gary Gregory <ggreg...@apache.org>
Committed: Wed Sep 21 11:01:32 2016 -0700

----------------------------------------------------------------------
 .../log4j/web/Log4jServletContextListener.java  | 42 +++++++++++++++-----
 1 file changed, 32 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/19832cf0/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jServletContextListener.java
----------------------------------------------------------------------
diff --git 
a/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jServletContextListener.java
 
b/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jServletContextListener.java
index f4afaba..4a65d92 100644
--- 
a/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jServletContextListener.java
+++ 
b/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jServletContextListener.java
@@ -16,12 +16,17 @@
  */
 package org.apache.logging.log4j.web;
 
+import java.util.Locale;
+import java.util.concurrent.TimeUnit;
+
 import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;
 
 import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.LifeCycle2;
 import org.apache.logging.log4j.status.StatusLogger;
+import org.apache.logging.log4j.util.Strings;
 
 /**
  * In environments older than Servlet 3.0, this initializer is responsible for 
starting up Log4j logging before anything
@@ -30,7 +35,13 @@ import org.apache.logging.log4j.status.StatusLogger;
  */
 public class Log4jServletContextListener implements ServletContextListener {
 
-    private static final Logger LOGGER = StatusLogger.getLogger();
+       private static final int DEFAULT_STOP_TIMEOUT = 30;
+    private static final TimeUnit DEFAULT_STOP_TIMEOUT_TIMEUNIT = 
TimeUnit.SECONDS;
+
+       private static final String KEY_STOP_TIMEOUT = "log4j.stop.timeout";
+       private static final String KEY_STOP_TIMEOUT_TIMEUNIT = 
"log4j.stop.timeout.timeunit";
+
+       private static final Logger LOGGER = StatusLogger.getLogger();
 
     private ServletContext servletContext;
     private Log4jWebLifeCycle initializer;
@@ -50,14 +61,25 @@ public class Log4jServletContextListener implements 
ServletContextListener {
     }
 
     @Override
-    public void contextDestroyed(final ServletContextEvent event) {
-        if (this.servletContext == null || this.initializer == null) {
-            LOGGER.warn("Context destroyed before it was initialized.");
-            return;
-        }
-        LOGGER.debug("Log4jServletContextListener ensuring that Log4j shuts 
down properly.");
+       public void contextDestroyed(final ServletContextEvent event) {
+               if (this.servletContext == null || this.initializer == null) {
+                       LOGGER.warn("Context destroyed before it was 
initialized.");
+                       return;
+               }
+               LOGGER.debug("Log4jServletContextListener ensuring that Log4j 
shuts down properly.");
 
-        this.initializer.clearLoggerContext(); // the application is finished 
shutting down now
-        this.initializer.stop();
-    }
+               this.initializer.clearLoggerContext(); // the application is 
finished
+               // shutting down now
+               if (initializer instanceof LifeCycle2) {
+                       final String stopTimeoutStr = 
servletContext.getInitParameter(KEY_STOP_TIMEOUT);
+                       final long stopTimeout = 
Strings.isEmpty(stopTimeoutStr) ? DEFAULT_STOP_TIMEOUT
+                                       : Long.parseLong(stopTimeoutStr);
+                       final String timeoutTimeUnitStr = 
servletContext.getInitParameter(KEY_STOP_TIMEOUT_TIMEUNIT);
+                       final TimeUnit timeoutTimeUnit = 
Strings.isEmpty(timeoutTimeUnitStr) ? DEFAULT_STOP_TIMEOUT_TIMEUNIT
+                                       : 
TimeUnit.valueOf(timeoutTimeUnitStr.toUpperCase(Locale.ROOT));
+                       ((LifeCycle2) this.initializer).stop(stopTimeout, 
timeoutTimeUnit);
+               } else {
+                       this.initializer.stop();
+               }
+       }
 }

Reply via email to