You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by jo...@apache.org on 2025/05/12 15:04:23 UTC

(sling-org-apache-sling-servlets-resolver) branch master updated: SLING-12433 fix concurrency issue when registering servlets (#59)

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

joerghoh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-servlets-resolver.git


The following commit(s) were added to refs/heads/master by this push:
     new 439d822  SLING-12433 fix concurrency issue when registering servlets (#59)
439d822 is described below

commit 439d822bb2e2aa686aa1b3e4621de20975bb252e
Author: Jörg Hoh <jo...@users.noreply.github.com>
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.
---
 .../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 df603c7..40be9f4 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
@@ -28,6 +28,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 jakarta.servlet.Servlet;
 import jakarta.servlet.ServletContext;
@@ -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<>();
 
@@ -275,20 +278,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);