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
The following commit(s) were added to refs/heads/10.1.x by this push:
new 0f540faf52 Fix concurrency issues with MD5 digests in
CloudMembershipProvider impls
0f540faf52 is described below
commit 0f540faf52d2862295eb18df686d3989b0817049
Author: Mark Thomas <[email protected]>
AuthorDate: Wed Jun 10 12:43:43 2026 +0100
Fix concurrency issues with MD5 digests in CloudMembershipProvider impls
---
.../membership/cloud/CloudMembershipProvider.java | 32 ++++++++++++++--------
.../membership/cloud/DNSMembershipProvider.java | 4 +--
.../cloud/KubernetesMembershipProvider.java | 4 +--
.../membership/cloud/LocalStrings.properties | 1 +
webapps/docs/changelog.xml | 4 +++
5 files changed, 30 insertions(+), 15 deletions(-)
diff --git
a/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipProvider.java
b/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipProvider.java
index 0d2b0888f0..46ff974194 100644
---
a/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipProvider.java
+++
b/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipProvider.java
@@ -27,6 +27,8 @@ import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.catalina.tribes.ChannelListener;
import org.apache.catalina.tribes.Heartbeat;
@@ -41,7 +43,10 @@ import org.apache.juli.logging.LogFactory;
* Abstract base class for cloud-based membership providers.
*/
public abstract class CloudMembershipProvider extends MembershipProviderBase
implements Heartbeat, ChannelListener {
+
private static final Log log =
LogFactory.getLog(CloudMembershipProvider.class);
+ private static final Queue<MessageDigest> queue = new
ConcurrentLinkedQueue<>();
+
/**
* String manager for this class.
*/
@@ -73,10 +78,6 @@ public abstract class CloudMembershipProvider extends
MembershipProviderBase imp
* The time when this provider started.
*/
protected Instant startTime;
- /**
- * MD5 message digest for hashing operations.
- */
- protected MessageDigest md5;
/**
* HTTP headers for cloud API requests.
@@ -98,14 +99,24 @@ public abstract class CloudMembershipProvider extends
MembershipProviderBase imp
protected long expirationTime = 5000;
/**
- * Creates a new CloudMembershipProvider and initializes the MD5 digest.
+ * Thread safe MD5 digest.
+ *
+ * @param input The bytes to digest
+ * @return The MD5 digest for the given input
*/
- public CloudMembershipProvider() {
- try {
- md5 = MessageDigest.getInstance("md5");
- } catch (NoSuchAlgorithmException e) {
- // Ignore
+ protected static byte[] digest(byte[] input) {
+ MessageDigest md = queue.poll();
+ if (md == null) {
+ try {
+ md = MessageDigest.getInstance("MD5");
+ } catch (NoSuchAlgorithmException e) {
+ // Newer JVMs are not required to support MD5
+ throw new
IllegalStateException(sm.getString("cloudMembershipProvider.noDigest"), e);
+ }
}
+ byte[] result = md.digest(input);
+ queue.add(md);
+ return result;
}
/**
@@ -229,5 +240,4 @@ public abstract class CloudMembershipProvider extends
MembershipProviderBase imp
public boolean accept(Serializable msg, Member sender) {
return false;
}
-
}
diff --git
a/java/org/apache/catalina/tribes/membership/cloud/DNSMembershipProvider.java
b/java/org/apache/catalina/tribes/membership/cloud/DNSMembershipProvider.java
index 5f44d5dc5c..497d0e6839 100644
---
a/java/org/apache/catalina/tribes/membership/cloud/DNSMembershipProvider.java
+++
b/java/org/apache/catalina/tribes/membership/cloud/DNSMembershipProvider.java
@@ -157,7 +157,7 @@ public class DNSMembershipProvider extends
CloudMembershipProvider {
if (inetAddresses != null) {
for (InetAddress inetAddress : inetAddresses) {
String ip = inetAddress.getHostAddress();
- byte[] id = md5.digest(ip.getBytes());
+ byte[] id = digest(ip.getBytes());
// We found ourselves, ignore
if (ip.equals(localIp)) {
// Update the UID on initial lookup
@@ -209,7 +209,7 @@ public class DNSMembershipProvider extends
CloudMembershipProvider {
buf.append('.').append(host[i] & 0xff);
}
- byte[] id = md5.digest(buf.toString().getBytes());
+ byte[] id = digest(buf.toString().getBytes());
member.setUniqueId(id);
member.setMemberAliveTime(-1);
updateMember(member, true);
diff --git
a/java/org/apache/catalina/tribes/membership/cloud/KubernetesMembershipProvider.java
b/java/org/apache/catalina/tribes/membership/cloud/KubernetesMembershipProvider.java
index f2e494d77f..2d8fb72783 100644
---
a/java/org/apache/catalina/tribes/membership/cloud/KubernetesMembershipProvider.java
+++
b/java/org/apache/catalina/tribes/membership/cloud/KubernetesMembershipProvider.java
@@ -270,7 +270,7 @@ public class KubernetesMembershipProvider extends
CloudMembershipProvider {
Member localMember = service.getLocalMember(false);
if (localMember.getUniqueId() ==
CloudMembershipService.INITIAL_ID &&
localMember instanceof MemberImpl) {
- byte[] id =
md5.digest(uid.getBytes(StandardCharsets.US_ASCII));
+ byte[] id =
digest(uid.getBytes(StandardCharsets.US_ASCII));
((MemberImpl) localMember).setUniqueId(id);
}
continue;
@@ -288,7 +288,7 @@ public class KubernetesMembershipProvider extends
CloudMembershipProvider {
log.error(sm.getString("kubernetesMembershipProvider.memberError"), ioe);
continue;
}
- byte[] id =
md5.digest(uid.getBytes(StandardCharsets.US_ASCII));
+ byte[] id = digest(uid.getBytes(StandardCharsets.US_ASCII));
member.setUniqueId(id);
members.add(member);
}
diff --git
a/java/org/apache/catalina/tribes/membership/cloud/LocalStrings.properties
b/java/org/apache/catalina/tribes/membership/cloud/LocalStrings.properties
index 3af508eb2b..632f49ccc6 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.noDigest=Unable to create an MD5 MessageDigest instance
cloudMembershipProvider.remove=Member [{0}] disappeared
cloudMembershipProvider.start=Namespace [{0}] set; clustering enabled
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index ce00fa581d..3de22dba3a 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -376,6 +376,10 @@
Fix some concurrency issues in <code>TwoPhaseCommitInterceptor</code>.
(markt)
</fix>
+ <fix>
+ Fix concurrency issues generating MD5 digests in the
+ <code>CloudMembershipProvider</code> implementations. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="WebSocket">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]