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]
