Author: markt Date: Thu Nov 4 23:03:26 2010 New Revision: 1031335 URL: http://svn.apache.org/viewvc?rev=1031335&view=rev Log: https://issues.apache.org/bugzilla/show_bug.cgi?id=50168 Add a DESTROYING state and associated events and use them to ensure Contexts are only destroyed once.
Modified: tomcat/trunk/java/org/apache/catalina/Lifecycle.java tomcat/trunk/java/org/apache/catalina/LifecycleState.java tomcat/trunk/java/org/apache/catalina/core/AprLifecycleListener.java tomcat/trunk/java/org/apache/catalina/core/ContainerBase.java tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java tomcat/trunk/java/org/apache/catalina/util/LifecycleBase.java tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/java/org/apache/catalina/Lifecycle.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Lifecycle.java?rev=1031335&r1=1031334&r2=1031335&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/Lifecycle.java (original) +++ tomcat/trunk/java/org/apache/catalina/Lifecycle.java Thu Nov 4 23:03:26 2010 @@ -50,10 +50,11 @@ package org.apache.catalina; * | | | | | | * | | | |auto | | * | | | destroy() \|/ destroy() | | - * | | FAILED ---->------ DESTROYED ----<----------------- | - * | | ^ | - * | | destroy() | | - * | ------------------------------- | + * | | FAILED ---->------ DESTROYING ---<----------------- | + * | | ^ | | + * | | destroy() | |auto | + * | ----------------------------- \|/ | + * | DESTROYED | * | | * | stop() | * --->------------------------------>------------------------------ @@ -149,9 +150,15 @@ public interface Lifecycle { /** - * The LifecycleEvent type for the "component destroy" event. + * The LifecycleEvent type for the "component after destroy" event. */ - public static final String DESTROY_EVENT = "destroy"; + public static final String AFTER_DESTROY_EVENT = "after_destroy"; + + + /** + * The LifecycleEvent type for the "component before destroy" event. + */ + public static final String BEFORE_DESTROY_EVENT = "before_destroy"; /** Modified: tomcat/trunk/java/org/apache/catalina/LifecycleState.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/LifecycleState.java?rev=1031335&r1=1031334&r2=1031335&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/LifecycleState.java (original) +++ tomcat/trunk/java/org/apache/catalina/LifecycleState.java Thu Nov 4 23:03:26 2010 @@ -31,7 +31,8 @@ public enum LifecycleState { STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT), STOPPING(false, Lifecycle.STOP_EVENT), STOPPED(false, Lifecycle.AFTER_STOP_EVENT), - DESTROYED(false, Lifecycle.DESTROY_EVENT), + DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT), + DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT), FAILED(false, null), MUST_STOP(true, null), MUST_DESTROY(true, null); Modified: tomcat/trunk/java/org/apache/catalina/core/AprLifecycleListener.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/AprLifecycleListener.java?rev=1031335&r1=1031334&r2=1031335&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/AprLifecycleListener.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/AprLifecycleListener.java Thu Nov 4 23:03:26 2010 @@ -110,7 +110,7 @@ public class AprLifecycleListener } } } - } else if (Lifecycle.DESTROY_EVENT.equals(event.getType())) { + } else if (Lifecycle.AFTER_DESTROY_EVENT.equals(event.getType())) { synchronized (lock) { if (!aprAvailable) { return; Modified: tomcat/trunk/java/org/apache/catalina/core/ContainerBase.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/ContainerBase.java?rev=1031335&r1=1031334&r2=1031335&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/ContainerBase.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/ContainerBase.java Thu Nov 4 23:03:26 2010 @@ -959,7 +959,12 @@ public abstract class ContainerBase exte // Set child's parent to null to prevent a loop child.setParent(null); try { - child.destroy(); + // 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(); + } } catch (LifecycleException e) { log.error("ContainerBase.removeChild: destroy: ", e); } Modified: tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java?rev=1031335&r1=1031334&r2=1031335&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java Thu Nov 4 23:03:26 2010 @@ -332,7 +332,7 @@ public class ContextConfig configureStop(); } else if (event.getType().equals(Lifecycle.AFTER_INIT_EVENT)) { init(); - } else if (event.getType().equals(Lifecycle.DESTROY_EVENT)) { + } else if (event.getType().equals(Lifecycle.AFTER_DESTROY_EVENT)) { destroy(); } Modified: tomcat/trunk/java/org/apache/catalina/util/LifecycleBase.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/util/LifecycleBase.java?rev=1031335&r1=1031334&r2=1031335&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/util/LifecycleBase.java (original) +++ tomcat/trunk/java/org/apache/catalina/util/LifecycleBase.java Thu Nov 4 23:03:26 2010 @@ -248,7 +248,8 @@ public abstract class LifecycleBase impl @Override public synchronized final void destroy() throws LifecycleException { - if (LifecycleState.DESTROYED.equals(state)) { + if (LifecycleState.DESTROYING.equals(state) || + LifecycleState.DESTROYED.equals(state)) { if (log.isDebugEnabled()) { Exception e = new LifecycleException(); @@ -265,9 +266,11 @@ public abstract class LifecycleBase impl if (!state.equals(LifecycleState.STOPPED) && !state.equals(LifecycleState.FAILED) && !state.equals(LifecycleState.NEW)) { - invalidTransition(Lifecycle.DESTROY_EVENT); + invalidTransition(Lifecycle.BEFORE_DESTROY_EVENT); } + setState(LifecycleState.DESTROYING); + destroyInternal(); setState(LifecycleState.DESTROYED); Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1031335&r1=1031334&r2=1031335&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Thu Nov 4 23:03:26 2010 @@ -80,6 +80,13 @@ resource. The default value is <code>true</code>, which will return the same instance of the resource in every JNDI lookup. (markt) </fix> + <fix> + <bug>50168</bug>: Separate the <code>Lifecycle.DESTROY_EVENT</code> into + <code>Lifecycle.BEFORE_DESTROY_EVENT</code> and + <code>Lifecycle.AFTER_DESTROY_EVENT</code>. Use the additional state to + ensure that <code>Context</code> objects are only destroyed once. + (markt) + </fix> <add> Improve debug logging for MapperListener registration. (markt) </add> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org