You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2019/06/03 16:03:06 UTC

[tomcat] branch master updated: Track listeners added by the FrameworkListener to remove them later

This is an automated email from the ASF dual-hosted git repository.

remm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/master by this push:
     new 0c6c3d2  Track listeners added by the FrameworkListener to remove them later
0c6c3d2 is described below

commit 0c6c3d2ebccb7400f904c5093450696b9e243746
Author: remm <re...@apache.org>
AuthorDate: Mon Jun 3 18:02:54 2019 +0200

    Track listeners added by the FrameworkListener to remove them later
    
    Avoid duplicate REMOVE_CHILD_EVENT notification, one for removeChild and
    a recursive one in child.destroy.
---
 java/org/apache/catalina/core/ContainerBase.java        |  6 +++++-
 java/org/apache/catalina/core/FrameworkListener.java    | 17 ++++++++++++++---
 .../core/ThreadLocalLeakPreventionListener.java         | 11 -----------
 3 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/java/org/apache/catalina/core/ContainerBase.java b/java/org/apache/catalina/core/ContainerBase.java
index 8bbfaf8..ad99bf3 100644
--- a/java/org/apache/catalina/core/ContainerBase.java
+++ b/java/org/apache/catalina/core/ContainerBase.java
@@ -808,18 +808,22 @@ public abstract class ContainerBase extends LifecycleMBeanBase
             log.error(sm.getString("containerBase.child.stop"), e);
         }
 
+        boolean destroy = false;
         try {
             // child.destroy() may have already been called which would have
             // triggered this call. If that is the case, no need to destroy the
             // child again.
             if (!LifecycleState.DESTROYING.equals(child.getState())) {
                 child.destroy();
+                destroy = true;
             }
         } catch (LifecycleException e) {
             log.error(sm.getString("containerBase.child.destroy"), e);
         }
 
-        fireContainerEvent(REMOVE_CHILD_EVENT, child);
+        if (!destroy) {
+            fireContainerEvent(REMOVE_CHILD_EVENT, child);
+        }
 
         synchronized(children) {
             if (children.get(child.getName()) == null)
diff --git a/java/org/apache/catalina/core/FrameworkListener.java b/java/org/apache/catalina/core/FrameworkListener.java
index 6e1944d..ba85ccb 100644
--- a/java/org/apache/catalina/core/FrameworkListener.java
+++ b/java/org/apache/catalina/core/FrameworkListener.java
@@ -17,6 +17,8 @@
 
 package org.apache.catalina.core;
 
+import java.util.concurrent.ConcurrentHashMap;
+
 import org.apache.catalina.Container;
 import org.apache.catalina.ContainerEvent;
 import org.apache.catalina.ContainerListener;
@@ -36,6 +38,9 @@ import org.apache.catalina.Service;
  */
 public abstract class FrameworkListener implements LifecycleListener, ContainerListener {
 
+    protected final ConcurrentHashMap<Context, LifecycleListener> contextListeners =
+            new ConcurrentHashMap<>();
+
     /**
      * Create a lifecycle listener which will then be added to the specified context.
      * @param context the associated Context
@@ -71,7 +76,6 @@ public abstract class FrameworkListener implements LifecycleListener, ContainerL
                 registerListenersForEngine(engine);
             }
         }
-
     }
 
     protected void registerListenersForEngine(Engine engine) {
@@ -90,7 +94,9 @@ public abstract class FrameworkListener implements LifecycleListener, ContainerL
     }
 
     protected void registerContextListener(Context context) {
-        context.addLifecycleListener(createLifecycleListener(context));
+        LifecycleListener listener = createLifecycleListener(context);
+        contextListeners.put(context, listener);
+        context.addLifecycleListener(listener);
     }
 
     protected void processContainerAddChild(Container child) {
@@ -104,7 +110,12 @@ public abstract class FrameworkListener implements LifecycleListener, ContainerL
     }
 
     protected void processContainerRemoveChild(Container child) {
-        if (child instanceof Host || child instanceof Engine) {
+        if (child instanceof Context) {
+            LifecycleListener listener = contextListeners.remove(child);
+            if (listener != null) {
+                child.removeLifecycleListener(listener);
+            }
+        } else if (child instanceof Host || child instanceof Engine) {
             child.removeContainerListener(this);
         }
     }
diff --git a/java/org/apache/catalina/core/ThreadLocalLeakPreventionListener.java b/java/org/apache/catalina/core/ThreadLocalLeakPreventionListener.java
index eb33b18..58c4857 100644
--- a/java/org/apache/catalina/core/ThreadLocalLeakPreventionListener.java
+++ b/java/org/apache/catalina/core/ThreadLocalLeakPreventionListener.java
@@ -19,7 +19,6 @@ package org.apache.catalina.core;
 
 import java.util.concurrent.Executor;
 
-import org.apache.catalina.Container;
 import org.apache.catalina.ContainerEvent;
 import org.apache.catalina.Context;
 import org.apache.catalina.Engine;
@@ -107,16 +106,6 @@ public class ThreadLocalLeakPreventionListener extends FrameworkListener {
 
     }
 
-    @Override
-    protected void processContainerRemoveChild(Container child) {
-        if (child instanceof Context) {
-            Context context = (Context) child;
-            context.removeLifecycleListener(this);
-        } else {
-            super.processContainerRemoveChild(child);
-        }
-    }
-
     /**
      * Updates each ThreadPoolExecutor with the current time, which is the time
      * when a context is being stopped.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org