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

markt-asf pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/9.0.x by this push:
     new 38dcae31ac Review "Reject non-positive membership timing properties at 
start"
38dcae31ac is described below

commit 38dcae31ac3890a7340ced9f64d34fdc74727ed8
Author: Mark Thomas <[email protected]>
AuthorDate: Thu Oct 22 18:44:15 2026 +0100

    Review "Reject non-positive membership timing properties at start"
    
    Additional checks
---
 .../catalina/tribes/membership/McastService.java   | 10 ++++++---
 .../membership/cloud/CloudMembershipProvider.java  |  4 ++++
 .../membership/cloud/CloudMembershipService.java   | 11 ++++++----
 .../membership/cloud/LocalStrings.properties       |  1 +
 .../tribes/membership/TestMcastService.java        |  3 ++-
 .../cloud/TestKubernetesMembershipProvider.java    | 25 ++++++++++++++++++++++
 6 files changed, 46 insertions(+), 8 deletions(-)

diff --git a/java/org/apache/catalina/tribes/membership/McastService.java 
b/java/org/apache/catalina/tribes/membership/McastService.java
index 900ed90271..16027c6075 100644
--- a/java/org/apache/catalina/tribes/membership/McastService.java
+++ b/java/org/apache/catalina/tribes/membership/McastService.java
@@ -393,18 +393,22 @@ public class McastService extends MembershipServiceBase 
implements MessageListen
             throw new IllegalArgumentException(
                     sm.getString("membershipService.invalidTimingProperty", 
"memberDropTime", Long.valueOf(dropTime)));
         }
+        // The recovery sleep time only matters if recovery is enabled
+        boolean recEnabled = 
Boolean.parseBoolean(properties.getProperty("recoveryEnabled"));
+        long recSlpTime = 
Long.parseLong(properties.getProperty("recoverySleepTime"));
+        if (recEnabled && recSlpTime <= 0) {
+            throw new 
IllegalArgumentException(sm.getString("membershipService.invalidTimingProperty",
+                    "recoverySleepTime", Long.valueOf(recSlpTime)));
+        }
 
         impl = new McastServiceImpl(localMember, frequency, dropTime,
                 Integer.parseInt(properties.getProperty("mcastPort")), bind,
                 
java.net.InetAddress.getByName(properties.getProperty("mcastAddress")), ttl, 
soTimeout, this, this,
                 
Boolean.parseBoolean(properties.getProperty("localLoopbackDisabled")));
         impl.setMembershipService(this);
-        String value = properties.getProperty("recoveryEnabled");
-        boolean recEnabled = Boolean.parseBoolean(value);
         impl.setRecoveryEnabled(recEnabled);
         int recCnt = 
Integer.parseInt(properties.getProperty("recoveryCounter"));
         impl.setRecoveryCounter(recCnt);
-        long recSlpTime = 
Long.parseLong(properties.getProperty("recoverySleepTime"));
         impl.setRecoverySleepTime(recSlpTime);
         impl.setChannel(channel);
 
diff --git 
a/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipProvider.java 
b/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipProvider.java
index b31b3efa37..ba2054b295 100644
--- 
a/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipProvider.java
+++ 
b/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipProvider.java
@@ -173,6 +173,10 @@ public abstract class CloudMembershipProvider extends 
MembershipProviderBase imp
         connectionTimeout = service.getConnectTimeout();
         readTimeout = service.getReadTimeout();
         expirationTime = service.getExpirationTime();
+        if (expirationTime <= 0) {
+            throw new 
IllegalArgumentException(sm.getString("cloudMembershipProvider.invalidTimingProperty",
+                    "expirationTime", Long.valueOf(expirationTime)));
+        }
 
         localIp = InetAddress.getLocalHost().getHostAddress();
         port = Integer.parseInt(properties.getProperty("tcpListenPort"));
diff --git 
a/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipService.java 
b/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipService.java
index 3037e9feb5..07b1e38686 100644
--- 
a/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipService.java
+++ 
b/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipService.java
@@ -162,10 +162,13 @@ public class CloudMembershipService extends 
MembershipServiceBase implements Clo
             if (log.isTraceEnabled()) {
                 log.trace("Using membershipProvider: " + provider);
             }
-            membershipProvider = (MembershipProvider) 
Class.forName(provider).getConstructor().newInstance();
-            membershipProvider.setMembershipListener(this);
-            membershipProvider.setMembershipService(this);
-            membershipProvider.init(properties);
+            MembershipProvider newProvider = (MembershipProvider) 
Class.forName(provider).getConstructor().newInstance();
+            newProvider.setMembershipListener(this);
+            newProvider.setMembershipService(this);
+            newProvider.init(properties);
+            // Only keep the provider once it has been initialised so that a 
rejected configuration does not leave an
+            // uninitialised provider behind for the next start
+            membershipProvider = newProvider;
         }
         membershipProvider.start(level);
 
diff --git 
a/java/org/apache/catalina/tribes/membership/cloud/LocalStrings.properties 
b/java/org/apache/catalina/tribes/membership/cloud/LocalStrings.properties
index ee641fcaeb..3f433d3635 100644
--- a/java/org/apache/catalina/tribes/membership/cloud/LocalStrings.properties
+++ b/java/org/apache/catalina/tribes/membership/cloud/LocalStrings.properties
@@ -25,6 +25,7 @@ abstractStream.trustManagerError=Could not create trust 
manager for [{0}]
 certificateStream.clientCertError=Could not create key manager for [{0}] 
([{1}])
 
 cloudMembershipProvider.add=Member [{0}] added
+cloudMembershipProvider.invalidTimingProperty=The timing property [{0}] is set 
to [{1}]. It must be greater than zero.
 cloudMembershipProvider.noDigest=Unable to create an MD5 MessageDigest instance
 cloudMembershipProvider.remove=Member [{0}] disappeared
 cloudMembershipProvider.start=Namespace [{0}] set; clustering enabled
diff --git a/test/org/apache/catalina/tribes/membership/TestMcastService.java 
b/test/org/apache/catalina/tribes/membership/TestMcastService.java
index fde5e37dd0..51fb7a4505 100644
--- a/test/org/apache/catalina/tribes/membership/TestMcastService.java
+++ b/test/org/apache/catalina/tribes/membership/TestMcastService.java
@@ -129,7 +129,8 @@ public class TestMcastService {
      */
     @Test
     public void testStartRejectsNonPositiveTimingProperties() throws Exception 
{
-        String[] invalid = { "mcastFrequency=0", "mcastFrequency=-1", 
"memberDropTime=0", "memberDropTime=-5" };
+        String[] invalid = { "mcastFrequency=0", "mcastFrequency=-1", 
"memberDropTime=0", "memberDropTime=-5",
+                "recoverySleepTime=0", "recoverySleepTime=-1" };
         for (String entry : invalid) {
             String[] property = entry.split("=");
             Properties props = new Properties();
diff --git 
a/test/org/apache/catalina/tribes/membership/cloud/TestKubernetesMembershipProvider.java
 
b/test/org/apache/catalina/tribes/membership/cloud/TestKubernetesMembershipProvider.java
index 9fc962c54e..335d3d1244 100644
--- 
a/test/org/apache/catalina/tribes/membership/cloud/TestKubernetesMembershipProvider.java
+++ 
b/test/org/apache/catalina/tribes/membership/cloud/TestKubernetesMembershipProvider.java
@@ -62,6 +62,31 @@ public class TestKubernetesMembershipProvider {
         }
     }
 
+
+    /*
+     * A non-positive expiration time expires every member on every heartbeat. 
Such a configuration must be
+     * rejected when the provider is initialised, and must not leave an 
uninitialised provider behind.
+     */
+    @Test
+    public void testStartRejectsNonPositiveExpirationTime() throws Exception {
+        for (long expirationTime : new long[] { 0, -5 }) {
+            GroupChannel channel = new GroupChannel();
+            channel.setName("TestKubernetesMembershipProvider-" + 
System.nanoTime());
+
+            CloudMembershipService service = new CloudMembershipService();
+            service.setChannel(channel);
+            service.setLocalMemberProperties("127.0.0.1", 4007, 0, 0);
+            service.setExpirationTime(expirationTime);
+            try {
+                service.start(CloudMembershipService.MBR_RX);
+                Assert.fail("start() must reject an expiration time of " + 
expirationTime);
+            } catch (IllegalArgumentException expected) {
+                // The configuration must be rejected before the provider is 
used
+            }
+            Assert.assertNull(service.getMembershipProvider());
+        }
+    }
+
     /*
      * The local member is resolved when the channel receiver starts, or is 
configured explicitly. Starting the
      * membership alone, without either, must fail with a clear error rather 
than a NumberFormatException from a


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

Reply via email to