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

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


The following commit(s) were added to refs/heads/main by this push:
     new 8d46615fdd Add FAILED_INIT lifecycle state
8d46615fdd is described below

commit 8d46615fdd248483e8f10cc6cd130839c429d508
Author: remm <r...@apache.org>
AuthorDate: Sat Oct 26 00:11:02 2024 +0200

    Add FAILED_INIT lifecycle state
    
    Differentiate FAILED after init, otherwise the component could become
    started.
    start() would call stop() after FAILED, despite the component never
    having completed init. After that the state might become STOPPED, paving
    the way for a subsequent successful start in some cases.
    This could happen with a TLS enabled connector in particular, where
    init() would fail for some reason.
---
 java/org/apache/catalina/LifecycleState.java     |  3 ++-
 java/org/apache/catalina/util/LifecycleBase.java | 23 ++++++++++++++++++-----
 webapps/docs/changelog.xml                       |  6 ++++++
 3 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/java/org/apache/catalina/LifecycleState.java 
b/java/org/apache/catalina/LifecycleState.java
index ec0fd2d10e..cc9a91005f 100644
--- a/java/org/apache/catalina/LifecycleState.java
+++ b/java/org/apache/catalina/LifecycleState.java
@@ -32,7 +32,8 @@ public enum LifecycleState {
     STOPPED(false, Lifecycle.AFTER_STOP_EVENT),
     DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),
     DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),
-    FAILED(false, null);
+    FAILED(false, null),
+    FAILED_INIT(false, null);
 
     private final boolean available;
     private final String lifecycleEvent;
diff --git a/java/org/apache/catalina/util/LifecycleBase.java 
b/java/org/apache/catalina/util/LifecycleBase.java
index ec7abb1b22..075a349a1a 100644
--- a/java/org/apache/catalina/util/LifecycleBase.java
+++ b/java/org/apache/catalina/util/LifecycleBase.java
@@ -153,9 +153,14 @@ public abstract class LifecycleBase implements Lifecycle {
 
         if (state.equals(LifecycleState.NEW)) {
             init();
-        } else if (state.equals(LifecycleState.FAILED)) {
+        }
+        if (state.equals(LifecycleState.FAILED)) {
             stop();
-        } else if (!state.equals(LifecycleState.INITIALIZED) && 
!state.equals(LifecycleState.STOPPED)) {
+        } else if (state.equals(LifecycleState.FAILED_INIT)) {
+            destroy();
+            return;
+        }
+        if (!state.equals(LifecycleState.INITIALIZED) && 
!state.equals(LifecycleState.STOPPED)) {
             invalidTransition(BEFORE_START_EVENT);
         }
 
@@ -285,7 +290,8 @@ public abstract class LifecycleBase implements Lifecycle {
         }
 
         if (!state.equals(LifecycleState.STOPPED) && 
!state.equals(LifecycleState.FAILED) &&
-                !state.equals(LifecycleState.NEW) && 
!state.equals(LifecycleState.INITIALIZED)) {
+                !state.equals(LifecycleState.NEW) && 
!state.equals(LifecycleState.INITIALIZED) &&
+                !state.equals(LifecycleState.FAILED_INIT)) {
             invalidTransition(BEFORE_DESTROY_EVENT);
         }
 
@@ -371,9 +377,12 @@ public abstract class LifecycleBase implements Lifecycle {
             // stopInternal() permits STOPPING_PREP to STOPPING and FAILED to
             // STOPPING
             if (!(state == LifecycleState.FAILED ||
+                    (this.state == LifecycleState.INITIALIZING && state == 
LifecycleState.FAILED_INIT) ||
+                    (this.state == LifecycleState.DESTROYING && state == 
LifecycleState.FAILED_INIT) ||
                     (this.state == LifecycleState.STARTING_PREP && state == 
LifecycleState.STARTING) ||
                     (this.state == LifecycleState.STOPPING_PREP && state == 
LifecycleState.STOPPING) ||
-                    (this.state == LifecycleState.FAILED && state == 
LifecycleState.STOPPING))) {
+                    (this.state == LifecycleState.FAILED && state == 
LifecycleState.STOPPING) ||
+                    (this.state == LifecycleState.FAILED_INIT && state == 
LifecycleState.DESTROYING))) {
                 // No other transition permitted
                 invalidTransition(state.name());
             }
@@ -394,7 +403,11 @@ public abstract class LifecycleBase implements Lifecycle {
 
 
     private void handleSubClassException(Throwable t, String key, Object... 
args) throws LifecycleException {
-        setStateInternal(LifecycleState.FAILED, null, false);
+        if (LifecycleState.INITIALIZING.equals(state) || 
LifecycleState.DESTROYING.equals(state)) {
+            setStateInternal(LifecycleState.FAILED_INIT, null, false);
+        } else {
+            setStateInternal(LifecycleState.FAILED, null, false);
+        }
         ExceptionUtils.handleThrowable(t);
         String msg = sm.getString(key, args);
         if (getThrowOnFailure()) {
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 2353c25812..6dc80dcb13 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -199,6 +199,12 @@
         Implement WebDAV <code>PROPPATCH</code> method using the newly added
         <code>PropertyStore</code>. (remm)
       </update>
+      <update>
+        Add new <code>lifecycleState.FAILED_INIT</code> to identify failures
+        during initialization. Otherwise, start and stop could be attempted
+        on a <code>Lifecycle</code> that did not go through initialization.
+        (remm)
+      </update>
     </changelog>
   </subsection>
   <subsection name="Coyote">


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

Reply via email to