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

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

commit f1178f87a369e750e70bda10e6fac84279c77f01
Author: opencode <[email protected]>
AuthorDate: Tue Oct 13 09:11:02 2026 +0200

    Avoid caching unregistered upgrade group infos
    
    The map of upgrade protocol name to UpgradeGroupInfo was populated
    before the attempt to register the group info with JMX. When that
    registration failed, only the local reference was nulled and the never
    registered instance remained cached, so every later upgrade for the
    protocol silently used an instance exposed by no MBean and the
    registration was never retried. The cached instances also survived
    destroy(), which had de-registered the upgrade MBeans, preventing any
    re-registration if the handler was later re-initialised.
    
    Restructure the lazy initialisation to only cache the group info once
    it is usable: registered with JMX when an ObjectName is available, or
    unconditionally when JMX registration is not possible, preserving the
    existing behaviour in that case. A failed registration now returns null
    to the caller, as it did before, and allows a later call to retry. In
    destroy(), clear the cached group infos under the monitor that guards
    their creation and registration so they are released and, if the
    handler is re-initialised, re-created and registered with JMX.
---
 .../coyote/http11/AbstractHttp11Protocol.java      | 36 +++++++++++++++-------
 1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/java/org/apache/coyote/http11/AbstractHttp11Protocol.java 
b/java/org/apache/coyote/http11/AbstractHttp11Protocol.java
index ca23f99175..b7ec72c203 100644
--- a/java/org/apache/coyote/http11/AbstractHttp11Protocol.java
+++ b/java/org/apache/coyote/http11/AbstractHttp11Protocol.java
@@ -107,16 +107,24 @@ public abstract class AbstractHttp11Protocol<S> extends 
AbstractProtocol<S> {
 
     @Override
     public void destroy() throws Exception {
-        // There may be upgrade protocols with their own MBeans. These need to
-        // be de-registered.
-        ObjectName rgOname = getGlobalRequestProcessorMBeanName();
-        if (rgOname != null) {
-            Registry registry = Registry.getRegistry(null);
-            ObjectName query = new ObjectName(rgOname.getCanonicalName() + 
",Upgrade=*");
-            Set<ObjectInstance> upgrades = 
registry.getMBeanServer().queryMBeans(query, null);
-            for (ObjectInstance upgrade : upgrades) {
-                registry.unregisterComponent(upgrade.getObjectName());
+        // Synchronise on the group info map to prevent an upgrade that is
+        // being created and registered from racing with the de-registration
+        // below and the clearing of the map.
+        synchronized (upgradeProtocolGroupInfos) {
+            // There may be upgrade protocols with their own MBeans. These need
+            // to be de-registered.
+            ObjectName rgOname = getGlobalRequestProcessorMBeanName();
+            if (rgOname != null) {
+                Registry registry = Registry.getRegistry(null);
+                ObjectName query = new ObjectName(rgOname.getCanonicalName() + 
",Upgrade=*");
+                Set<ObjectInstance> upgrades = 
registry.getMBeanServer().queryMBeans(query, null);
+                for (ObjectInstance upgrade : upgrades) {
+                    registry.unregisterComponent(upgrade.getObjectName());
+                }
             }
+            // Release the cached group infos so they are freed and, if the
+            // handler is re-initialised, re-created and registered with JMX.
+            upgradeProtocolGroupInfos.clear();
         }
 
         super.destroy();
@@ -909,7 +917,9 @@ public abstract class AbstractHttp11Protocol<S> extends 
AbstractProtocol<S> {
      * Get the upgrade group info for the specified upgrade protocol.
      *
      * @param upgradeProtocol The upgrade protocol name
-     * @return The upgrade group info for the specified protocol
+     * @return The upgrade group info for the specified protocol, or
+     *             {@code null} if the protocol name is null or the statistics
+     *             MBean for the protocol could not be registered
      */
     public UpgradeGroupInfo getUpgradeGroupInfo(String upgradeProtocol) {
         if (upgradeProtocol == null) {
@@ -923,16 +933,20 @@ public abstract class AbstractHttp11Protocol<S> extends 
AbstractProtocol<S> {
                 result = upgradeProtocolGroupInfos.get(upgradeProtocol);
                 if (result == null) {
                     result = new UpgradeGroupInfo();
-                    upgradeProtocolGroupInfos.put(upgradeProtocol, result);
                     ObjectName oname = getONameForUpgrade(upgradeProtocol);
                     if (oname != null) {
                         try {
                             
Registry.getRegistry(null).registerComponent(result, oname, null);
                         } catch (Exception e) {
                             
getLog().warn(sm.getString("abstractHttp11Protocol.upgradeJmxRegistrationFail"),
 e);
+                            // Do not cache the result so that a later call can
+                            // retry the registration.
                             result = null;
                         }
                     }
+                    if (result != null) {
+                        upgradeProtocolGroupInfos.put(upgradeProtocol, result);
+                    }
                 }
             }
         }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to