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

jsedding pushed a commit to branch resolver-2.x-backports
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-servlets-resolver.git

commit 84114986facc68744af3bcc6ab179923f036aa19
Author: Jörg Hoh <[email protected]>
AuthorDate: Mon May 12 17:04:18 2025 +0200

    SLING-12433 fix concurrency issue when registering servlets (#59)
    
    use locking to prevent ConcurrentModificationExceptions when servlets are 
registered concurrently.
    
    (cherry picked from commit 439d822bb2e2aa686aa1b3e4621de20975bb252e)
---
 .../resolver/internal/resource/ServletMounter.java | 34 ++++++++++++++--------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletMounter.java
 
b/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletMounter.java
index 757e036..516aa95 100644
--- 
a/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletMounter.java
+++ 
b/src/main/java/org/apache/sling/servlets/resolver/internal/resource/ServletMounter.java
@@ -32,6 +32,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.sling.api.request.RequestUtil;
 import org.apache.sling.api.resource.ResourceResolverFactory;
@@ -90,6 +92,7 @@ public class ServletMounter {
     private final MergingServletResourceProvider provider;
 
     private final Set<ServiceRegistration<?>> providerRegs;
+    private final Lock providerRegsLock = new ReentrantLock(); // to guard 
concurrent access to the providerRegs
 
     private final ConcurrentHashMap<ResolutionCache, ResolutionCache> 
resolutionCaches = new ConcurrentHashMap<>();
 
@@ -249,20 +252,27 @@ public class ServletMounter {
                     if (this.provider != null) {
                         this.provider.add(srProvider, reference);
                         if (pathProviders) {
-                            outer:
-                            for (final String path : 
srProvider.getServletPaths()) {
-                                String root =
-                                        path.indexOf('/', 1) != -1 ? 
path.substring(0, path.indexOf('/', 1) + 1) : path;
-                                for (ServiceRegistration<?> reg : 
providerRegs) {
-                                    if 
(root.equals(reg.getReference().getProperty(ResourceProvider.PROPERTY_ROOT))) {
-                                        continue outer;
+                            providerRegsLock.lock();
+                            try {
+                                outer:
+                                for (final String path : 
srProvider.getServletPaths()) {
+                                    String root = path.indexOf('/', 1) != -1
+                                            ? path.substring(0, 
path.indexOf('/', 1) + 1)
+                                            : path;
+                                    for (ServiceRegistration<?> reg : 
providerRegs) {
+                                        if (root.equals(
+                                                
reg.getReference().getProperty(ResourceProvider.PROPERTY_ROOT))) {
+                                            continue outer;
+                                        }
                                     }
+                                    final Dictionary<String, Object> params = 
new Hashtable<>();
+                                    params.put(ResourceProvider.PROPERTY_ROOT, 
root);
+                                    params.put(Constants.SERVICE_DESCRIPTION, 
"ServletResourceProvider for Servlets");
+                                    params.put(ResourceProvider.PROPERTY_MODE, 
ResourceProvider.MODE_PASSTHROUGH);
+                                    
providerRegs.add(context.registerService(ResourceProvider.class, provider, 
params));
                                 }
-                                final Dictionary<String, Object> params = new 
Hashtable<>();
-                                params.put(ResourceProvider.PROPERTY_ROOT, 
root);
-                                params.put(Constants.SERVICE_DESCRIPTION, 
"ServletResourceProvider for Servlets");
-                                params.put(ResourceProvider.PROPERTY_MODE, 
ResourceProvider.MODE_PASSTHROUGH);
-                                
providerRegs.add(context.registerService(ResourceProvider.class, provider, 
params));
+                            } finally {
+                                providerRegsLock.unlock();
                             }
                         }
                         
resolutionCaches.values().forEach(ResolutionCache::flushCache);

Reply via email to