You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2026/06/19 12:46:45 UTC
(tomcat) branch 9.0.x updated: Fix a race with two requests looking up a singleton JNDI resource
This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/9.0.x by this push:
new 5d2be5745d Fix a race with two requests looking up a singleton JNDI resource
5d2be5745d is described below
commit 5d2be5745dcb264ad4ba46a49f5b716b0afef63e
Author: Mark Thomas <ma...@apache.org>
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 | 8 +++++
2 files changed, 46 insertions(+), 20 deletions(-)
diff --git a/java/org/apache/naming/NamingContext.java b/java/org/apache/naming/NamingContext.java
index 7f680a43d3..5da0f2d522 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 0abb3ec97b..27bb378fbd 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -108,6 +108,14 @@
issues do not "pop up" wrt. others).
-->
<section name="Tomcat 9.0.120 (remm)" rtext="in development">
+ <subsection name="Catalina">
+ <changelog>
+ <fix>
+ Avoid a race condition with concurrent lookups for a singleton JNDI
+ resource. (markt)
+ </fix>
+ </changelog>
+ </subsection>
</section>
<section name="Tomcat 9.0.119 (remm)" rtext="release in progress">
<subsection name="Catalina">
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org