This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push:
new 3c6cd2eab3 Fix a race with two requests looking up a singleton JNDI
resource
3c6cd2eab3 is described below
commit 3c6cd2eab3f012f32002b1b342451073732ab2ba
Author: Mark Thomas <[email protected]>
AuthorDate: Fri Jun 19 13:35:49 2026 +0100
Fix a race with two requests looking up a singleton JNDI resource
---
java/org/apache/naming/NamingContext.java | 58 ++++++++++++++++++++-----------
webapps/docs/changelog.xml | 4 +++
2 files changed, 42 insertions(+), 20 deletions(-)
diff --git a/java/org/apache/naming/NamingContext.java
b/java/org/apache/naming/NamingContext.java
index 2bb5274ba4..b6712c3eea 100644
--- a/java/org/apache/naming/NamingContext.java
+++ b/java/org/apache/naming/NamingContext.java
@@ -518,28 +518,28 @@ public class NamingContext implements Context {
} else if (entry.type == NamingEntry.REFERENCE) {
try {
Object obj = null;
- if (!GRAAL) {
- obj = NamingManager.getObjectInstance(entry.value,
name, this, env);
- } else {
- // NamingManager.getObjectInstance would simply return
the reference here
- // Use the configured object factory to resolve it
directly if possible
- // Note: This may need manual constructor reflection
configuration
- Reference reference = (Reference) entry.value;
- String factoryClassName =
reference.getFactoryClassName();
- if (factoryClassName != null) {
- Class<?> factoryClass =
getClass().getClassLoader().loadClass(factoryClassName);
- ObjectFactory factory = (ObjectFactory)
factoryClass.getDeclaredConstructor().newInstance();
- obj = factory.getObjectInstance(entry.value, name,
this, env);
- }
- }
+ boolean singleton = false;
if (entry.value instanceof ResourceRef) {
- boolean singleton = Boolean.parseBoolean(
- (String) ((ResourceRef)
entry.value).get(ResourceRef.SINGLETON).getContent());
- if (singleton) {
- entry.type = NamingEntry.ENTRY;
- entry.value = obj;
+ // Only create singleton instances inside the sync
+ synchronized (entry) {
+ if (entry.value instanceof ResourceRef) {
+ singleton = Boolean.parseBoolean(
+ (String) ((ResourceRef)
entry.value).get(ResourceRef.SINGLETON).getContent());
+ if (singleton) {
+ obj = getObjectInstance(name, entry);
+ entry.type = NamingEntry.ENTRY;
+ entry.value = obj;
+ }
+ } else {
+ // Another thread has created the singleton
+ singleton = true;
+ obj = entry.value;
+ }
}
}
+ if (!singleton) {
+ obj = getObjectInstance(name, entry);
+ }
if (obj == null) {
throw new
NamingException(sm.getString("namingContext.failResolvingReference", name));
}
@@ -557,10 +557,28 @@ public class NamingContext implements Context {
return entry.value;
}
}
-
}
+ private Object getObjectInstance(Name name, NamingEntry entry) throws
Exception {
+ Object obj = null;
+ if (!GRAAL) {
+ obj = NamingManager.getObjectInstance(entry.value, name, this,
env);
+ } else {
+ // NamingManager.getObjectInstance would simply return the
reference here
+ // Use the configured object factory to resolve it directly if
possible
+ // Note: This may need manual constructor reflection configuration
+ Reference reference = (Reference) entry.value;
+ String factoryClassName = reference.getFactoryClassName();
+ if (factoryClassName != null) {
+ Class<?> factoryClass =
getClass().getClassLoader().loadClass(factoryClassName);
+ ObjectFactory factory = (ObjectFactory)
factoryClass.getDeclaredConstructor().newInstance();
+ obj = factory.getObjectInstance(entry.value, name, this, env);
+ }
+ }
+ return obj;
+ }
+
/**
* Binds a name to an object. All intermediate contexts and the target
context (that named by all but terminal
* atomic component of the name) must already exist.
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 17c29a517d..588a5a3803 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -218,6 +218,10 @@
third-party library version information. (csutherl)
</add>
<!-- Entries for backport and removal before 12.0.0-M1 below this line
-->
+ <fix>
+ Avoid a race condition with concurrent lookups for a singleton JNDI
+ resource. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]