This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch 11.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/11.0.x by this push:
new 79ba91ee85 Review "Guard the sender recovery trigger against a
concurrent stop"
79ba91ee85 is described below
commit 79ba91ee85d70a8dba92790f1390ea529d321aab
Author: Mark Thomas <[email protected]>
AuthorDate: Thu Oct 22 14:26:19 2026 +0100
Review "Guard the sender recovery trigger against a concurrent stop"
Close some timing gaps
---
.../tribes/membership/LocalStrings.properties | 1 +
.../tribes/membership/McastServiceImpl.java | 55 +++++++++++++++++-----
2 files changed, 43 insertions(+), 13 deletions(-)
diff --git a/java/org/apache/catalina/tribes/membership/LocalStrings.properties
b/java/org/apache/catalina/tribes/membership/LocalStrings.properties
index a5cbad68cb..a3422e4721 100644
--- a/java/org/apache/catalina/tribes/membership/LocalStrings.properties
+++ b/java/org/apache/catalina/tribes/membership/LocalStrings.properties
@@ -44,6 +44,7 @@ mcastServiceImpl.messageError=Unable to decode message
mcastServiceImpl.receive.running=McastService.receive already running.
mcastServiceImpl.recovery=Tribes membership running recovery thread.
Multicasting is not functional.
mcastServiceImpl.recovery.failed=Recovery attempt number [{0}] failed. Trying
again in [{1}] seconds.
+mcastServiceImpl.recovery.halted=Recovery halted as membership service has
been explicitly stopped.
mcastServiceImpl.recovery.startFailed=Recovery thread failed to start
membership service.
mcastServiceImpl.recovery.stopFailed=Recovery thread failed to stop membership
service.
mcastServiceImpl.recovery.successful=Membership recovery was successful.
diff --git a/java/org/apache/catalina/tribes/membership/McastServiceImpl.java
b/java/org/apache/catalina/tribes/membership/McastServiceImpl.java
index 60935bb95f..e5c99ed582 100644
--- a/java/org/apache/catalina/tribes/membership/McastServiceImpl.java
+++ b/java/org/apache/catalina/tribes/membership/McastServiceImpl.java
@@ -40,9 +40,9 @@ import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
/**
- * A <b>membership</b> implementation using simple multicast. This class is
responsible for maintaining a list of
- * active cluster nodes in the cluster. If a node fails to send out a
heartbeat, the node will be dismissed. This is the
- * low level implementation that handles the multicasting sockets.
+ * A <b>membership</b> implementation using simple multicast. This class is
responsible for maintaining a list of active
+ * cluster nodes in the cluster. If a node fails to send out a heartbeat, the
node will be dismissed. This is the low
+ * level implementation that handles the multicasting sockets.
*/
public class McastServiceImpl extends MembershipProviderBase {
@@ -54,9 +54,8 @@ public class McastServiceImpl extends MembershipProviderBase {
protected static final int MAX_PACKET_SIZE = 65535;
/**
- * The maximum payload size of a packet that can be sent. This is lower
than the maximum
- * packet size because the protocol limit for a UDP datagram includes the
IP and UDP headers,
- * and the IP header may be extended by options.
+ * The maximum payload size of a packet that can be sent. This is lower
than the maximum packet size because the
+ * protocol limit for a UDP datagram includes the IP and UDP headers, and
the IP header may be extended by options.
*/
protected static final int MAX_SEND_SIZE = MAX_PACKET_SIZE - 48;
@@ -537,7 +536,8 @@ public class McastServiceImpl extends
MembershipProviderBase {
* Send a packet.
*
* @param checkexpired whether to check for expired members
- * @param packet the packet to send
+ * @param packet the packet to send
+ *
* @throws IOException if send fails
*/
public void send(boolean checkexpired, DatagramPacket packet) throws
IOException {
@@ -567,6 +567,7 @@ public class McastServiceImpl extends
MembershipProviderBase {
/**
* Get the service start time.
+ *
* @return the service start time
*/
public long getServiceStartTime() {
@@ -575,6 +576,7 @@ public class McastServiceImpl extends
MembershipProviderBase {
/**
* Get the recovery counter.
+ *
* @return the recovery counter
*/
public int getRecoveryCounter() {
@@ -583,6 +585,7 @@ public class McastServiceImpl extends
MembershipProviderBase {
/**
* Check if recovery is enabled.
+ *
* @return true if recovery is enabled
*/
public boolean isRecoveryEnabled() {
@@ -591,6 +594,7 @@ public class McastServiceImpl extends
MembershipProviderBase {
/**
* Get the recovery sleep time.
+ *
* @return the recovery sleep time
*/
public long getRecoverySleepTime() {
@@ -599,6 +603,7 @@ public class McastServiceImpl extends
MembershipProviderBase {
/**
* Get the channel.
+ *
* @return the channel
*/
public Channel getChannel() {
@@ -607,6 +612,7 @@ public class McastServiceImpl extends
MembershipProviderBase {
/**
* Set the channel.
+ *
* @param channel the channel to set
*/
public void setChannel(Channel channel) {
@@ -687,6 +693,7 @@ public class McastServiceImpl extends
MembershipProviderBase {
/**
* Constructor.
+ *
* @param time the send interval
*/
public SenderThread(long time) {
@@ -739,6 +746,7 @@ public class McastServiceImpl extends
MembershipProviderBase {
/**
* Recover the mcast service.
+ *
* @param parent the parent service
*/
public static synchronized void recover(McastServiceImpl parent) {
@@ -769,6 +777,7 @@ public class McastServiceImpl extends
MembershipProviderBase {
/**
* Constructor.
+ *
* @param parent the parent service
*/
public RecoveryThread(McastServiceImpl parent) {
@@ -777,6 +786,7 @@ public class McastServiceImpl extends
MembershipProviderBase {
/**
* Stop the service.
+ *
* @return true if stopped successfully
*/
public boolean stopService() {
@@ -791,12 +801,15 @@ public class McastServiceImpl extends
MembershipProviderBase {
/**
* Start the service.
+ *
+ * @param recoveryLevel Services to (re)start
+ *
* @return true if started successfully
*/
- public boolean startService() {
+ public boolean startService(int recoveryLevel) {
try {
parent.init();
- parent.start(Channel.MBR_RX_SEQ | Channel.MBR_TX_SEQ);
+ parent.start(recoveryLevel);
return true;
} catch (Exception e) {
log.warn(sm.getString("mcastServiceImpl.recovery.startFailed"), e);
@@ -814,10 +827,23 @@ public class McastServiceImpl extends
MembershipProviderBase {
log.info(sm.getString("mcastServiceImpl.recovery"));
}
// Non short-circuit AND since we want both stop and start
to execute
- if (stopService() & startService()) {
- success = true;
- if (log.isInfoEnabled()) {
-
log.info(sm.getString("mcastServiceImpl.recovery.successful"));
+ synchronized (parent) {
+ int recoveryLevel = parent.startLevel;
+ if (recoveryLevel > 0) {
+ if (stopService() & startService(recoveryLevel)) {
+ success = true;
+ if (log.isInfoEnabled()) {
+
log.info(sm.getString("mcastServiceImpl.recovery.successful"));
+ }
+ } else {
+ // This is a hack to enable detection of an
explicit stop() call between recovery attempts
+ parent.startLevel = recoveryLevel;
+ }
+ } else {
+ success = true;
+ if (log.isInfoEnabled()) {
+
log.info(sm.getString("mcastServiceImpl.recovery.halted"));
+ }
}
}
try {
@@ -839,6 +865,7 @@ public class McastServiceImpl extends
MembershipProviderBase {
/**
* Set the recovery counter.
+ *
* @param recoveryCounter the recovery counter
*/
public void setRecoveryCounter(int recoveryCounter) {
@@ -847,6 +874,7 @@ public class McastServiceImpl extends
MembershipProviderBase {
/**
* Set whether recovery is enabled.
+ *
* @param recoveryEnabled whether recovery is enabled
*/
public void setRecoveryEnabled(boolean recoveryEnabled) {
@@ -855,6 +883,7 @@ public class McastServiceImpl extends
MembershipProviderBase {
/**
* Set the recovery sleep time.
+ *
* @param recoverySleepTime the recovery sleep time
*/
public void setRecoverySleepTime(long recoverySleepTime) {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]