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

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

commit 1e8fea97f9de3c425ac2423bf2c6e5bf9f57971a
Author: opencode <[email protected]>
AuthorDate: Sun Oct 11 11:41:40 2026 +0200

    Fail clearly when static membership starts without a local member
    
    The static membership service dereferenced its local member when it
    started, although the member is only known once the channel receiver
    has started, or when it was configured explicitly. Starting the
    membership at a level that does not include the receiver therefore
    ended in a null pointer exception wrapped into a channel exception,
    with no hint at the missing configuration.
    
    The service now reports an illegal state exception naming the two ways
    of providing the local member, before building anything, so the failed
    start leaves the service untouched and a later start that resolves the
    member works as before.
    
    Add a test that a start with an unknown local member fails with that
    exception and leaves no provider behind.
---
 .../tribes/membership/LocalStrings.properties       |  1 +
 .../tribes/membership/StaticMembershipService.java  |  5 +++++
 .../membership/TestStaticMembershipService.java     | 21 +++++++++++++++++++++
 3 files changed, 27 insertions(+)

diff --git a/java/org/apache/catalina/tribes/membership/LocalStrings.properties 
b/java/org/apache/catalina/tribes/membership/LocalStrings.properties
index 97d1dbdb5b..b7fd3273a8 100644
--- a/java/org/apache/catalina/tribes/membership/LocalStrings.properties
+++ b/java/org/apache/catalina/tribes/membership/LocalStrings.properties
@@ -74,5 +74,6 @@ staticMembershipProvider.replyRequest.ignored=Message [{0}] 
is ignored.
 staticMembershipProvider.startMembership.noReplies=Received 0 replies, 
probably a timeout.
 staticMembershipProvider.stopMembership.sendFailed=Unable to send stop 
membership message.
 
+staticMembershipService.localMemberNotSet=The local member has not been 
resolved. Either start the channel with a level that includes the receiver or 
configure the local member explicitly.
 staticMembershipService.noLocalMember=There is no localMember in static member 
list.
 staticMembershipService.stopFail=Unable to stop the static membership service, 
level: [{0}]
diff --git 
a/java/org/apache/catalina/tribes/membership/StaticMembershipService.java 
b/java/org/apache/catalina/tribes/membership/StaticMembershipService.java
index 74c0405eb0..841a49985a 100644
--- a/java/org/apache/catalina/tribes/membership/StaticMembershipService.java
+++ b/java/org/apache/catalina/tribes/membership/StaticMembershipService.java
@@ -68,6 +68,11 @@ public class StaticMembershipService extends 
MembershipServiceBase implements St
             provider.start(level);
             return;
         }
+        if (localMember == null) {
+            // The local member is resolved when the channel receiver starts, 
or is configured
+            // explicitly. Starting the membership without either leaves it 
unknown.
+            throw new 
IllegalStateException(sm.getString("staticMembershipService.localMemberNotSet"));
+        }
         localMember.setServiceStartTime(System.currentTimeMillis());
         localMember.setMemberAliveTime(100);
         // build membership provider
diff --git 
a/test/org/apache/catalina/tribes/membership/TestStaticMembershipService.java 
b/test/org/apache/catalina/tribes/membership/TestStaticMembershipService.java
index c2b3992f18..a72fc0b7c7 100644
--- 
a/test/org/apache/catalina/tribes/membership/TestStaticMembershipService.java
+++ 
b/test/org/apache/catalina/tribes/membership/TestStaticMembershipService.java
@@ -74,4 +74,25 @@ public class TestStaticMembershipService {
         service.start(level);
         service.stop(level);
     }
+
+    /*
+     * 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 the null pointer exception that dereferencing the missing 
member caused.
+     */
+    @Test
+    public void testStartWithoutLocalMemberFails() throws Exception {
+        GroupChannel channel = new GroupChannel();
+        channel.setName("TestStaticMembershipService-" + System.nanoTime());
+
+        StaticMembershipService service = new StaticMembershipService();
+        service.setChannel(channel);
+        try {
+            service.start(Channel.MBR_TX_SEQ);
+            Assert.fail("start() must fail when the local member is unknown");
+        } catch (IllegalStateException expected) {
+            // A clear configuration error rather than a null pointer exception
+        }
+        Assert.assertNull(service.getMembershipProvider());
+    }
 }


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

Reply via email to