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

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

commit 307d0d5162fc3bbf0556fd9fe09d5e920c84baaa
Author: Mark Thomas <[email protected]>
AuthorDate: Fri May 15 11:26:30 2026 +0100

    Fix inconsistent getters and setters
    
    This started with a CodeQL error for inconsistent syncs
    While examining the code, I saw that the listeners were not being
    cleared consistently.
    With most of the listener fixes in place a CoPilot review found a couple
    of further instances.
    Ensure tests pass with updated code.
---
 .../catalina/tribes/group/ChannelCoordinator.java  | 38 ++++++++++++++++------
 .../group/interceptors/TestTcpFailureDetector.java |  4 +--
 webapps/docs/changelog.xml                         |  4 +++
 3 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/java/org/apache/catalina/tribes/group/ChannelCoordinator.java 
b/java/org/apache/catalina/tribes/group/ChannelCoordinator.java
index ff5888ba41..3acf580994 100644
--- a/java/org/apache/catalina/tribes/group/ChannelCoordinator.java
+++ b/java/org/apache/catalina/tribes/group/ChannelCoordinator.java
@@ -240,6 +240,9 @@ public class ChannelCoordinator extends 
ChannelInterceptorBase implements Messag
             }
             if (Channel.MBR_RX_SEQ == (svc & Channel.MBR_RX_SEQ)) {
                 membershipService.stop(MembershipService.MBR_RX);
+                if (membershipService instanceof McastService) {
+                    ((McastService) 
membershipService).setMessageListener(null);
+                }
                 membershipService.setMembershipListener(null);
                 valid = true;
 
@@ -295,7 +298,7 @@ public class ChannelCoordinator extends 
ChannelInterceptorBase implements Messag
      *
      * @return the cluster receiver
      */
-    public ChannelReceiver getClusterReceiver() {
+    public synchronized ChannelReceiver getClusterReceiver() {
         return clusterReceiver;
     }
 
@@ -313,7 +316,7 @@ public class ChannelCoordinator extends 
ChannelInterceptorBase implements Messag
      *
      * @return the membership service
      */
-    public MembershipService getMembershipService() {
+    public synchronized MembershipService getMembershipService() {
         return membershipService;
     }
 
@@ -326,14 +329,15 @@ public class ChannelCoordinator extends 
ChannelInterceptorBase implements Messag
         if (startLevel != 0) {
             throw new 
IllegalStateException(sm.getString("channelCoordinator.invalidState.notStopped"));
         }
-        if (clusterReceiver != null) {
-            this.clusterReceiver = clusterReceiver;
+        if (this.clusterReceiver == clusterReceiver) {
+            return;
+        }
+        if (this.clusterReceiver != null) {
+            this.clusterReceiver.setMessageListener(null);
+        }
+        this.clusterReceiver = clusterReceiver;
+        if (this.clusterReceiver != null) {
             this.clusterReceiver.setMessageListener(this);
-        } else {
-            if (this.clusterReceiver != null) {
-                this.clusterReceiver.setMessageListener(null);
-            }
-            this.clusterReceiver = null;
         }
     }
 
@@ -358,8 +362,22 @@ public class ChannelCoordinator extends 
ChannelInterceptorBase implements Messag
         if (startLevel != 0) {
             throw new 
IllegalStateException(sm.getString("channelCoordinator.invalidState.notStopped"));
         }
+        if (this.membershipService == membershipService) {
+            return;
+        }
+        if (this.membershipService != null) {
+            this.membershipService.setMembershipListener(null);
+            if (this.membershipService instanceof McastService) {
+                ((McastService) 
this.membershipService).setMessageListener(null);
+            }
+        }
         this.membershipService = membershipService;
-        this.membershipService.setMembershipListener(this);
+        if (this.membershipService != null) {
+            this.membershipService.setMembershipListener(this);
+            if (this.membershipService instanceof McastService) {
+                ((McastService) 
this.membershipService).setMessageListener(this);
+            }
+        }
     }
 
     @Override
diff --git 
a/test/org/apache/catalina/tribes/group/interceptors/TestTcpFailureDetector.java
 
b/test/org/apache/catalina/tribes/group/interceptors/TestTcpFailureDetector.java
index ea68988724..7c8a87c699 100644
--- 
a/test/org/apache/catalina/tribes/group/interceptors/TestTcpFailureDetector.java
+++ 
b/test/org/apache/catalina/tribes/group/interceptors/TestTcpFailureDetector.java
@@ -71,7 +71,7 @@ public class TestTcpFailureDetector {
         clear();
         channel1.start(Channel.DEFAULT);
         channel2.start(Channel.DEFAULT);
-        //Thread.sleep(1000);
+        Thread.sleep(1000);
         Assert.assertEquals("Expecting member count to be 
equal",mbrlist1.members.size(),mbrlist2.members.size());
         channel2.stop(Channel.SND_RX_SEQ);
         ByteMessage msg = new ByteMessage(new byte[1024]);
@@ -129,7 +129,7 @@ public class TestTcpFailureDetector {
         clear();
         channel1.start(Channel.DEFAULT);
         channel2.start(Channel.DEFAULT);
-        //Thread.sleep(1000);
+        Thread.sleep(1000);
         Assert.assertEquals("Expecting member count to be 
equal",mbrlist1.members.size(),mbrlist2.members.size());
         channel2.stop(Channel.MBR_TX_SEQ);
         ByteMessage msg = new ByteMessage(new byte[1024]);
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 8ab3e9eae9..410d3d192a 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -139,6 +139,10 @@
         membership is configured without a trust store as all certificates will
         be trusted in this configuration. (markt)
       </fix>
+      <fix>
+        Ensure listeners are correctly added and removed when configuring the
+        channel coordinator. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Web applications">


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

Reply via email to