You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2016/03/22 11:52:16 UTC

svn commit: r1736182 - in /sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers: ResourceProviderHandler.java ResourceProviderTracker.java

Author: cziegeler
Date: Tue Mar 22 10:52:16 2016
New Revision: 1736182

URL: http://svn.apache.org/viewvc?rev=1736182&view=rev
Log:
SLING-5622 : Deadlock between service unregister (thus unbindTopologyEventListener) and discoveryLiteCheck

Modified:
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderHandler.java
    sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTracker.java

Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderHandler.java?rev=1736182&r1=1736181&r2=1736182&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderHandler.java (original)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderHandler.java Tue Mar 22 10:52:16 2016
@@ -38,6 +38,8 @@ public class ResourceProviderHandler imp
 
     private volatile boolean isUsed = false;
 
+    private volatile long activationCount;
+
     public ResourceProviderHandler(final BundleContext bc, final ResourceProviderInfo info) {
         this.info = info;
         this.bundleContext = bc;
@@ -49,14 +51,26 @@ public class ResourceProviderHandler imp
 
     @SuppressWarnings("unchecked")
     public boolean activate() {
-        this.provider = (ResourceProvider<Object>) this.bundleContext.getService(this.info.getServiceReference());
-        if ( this.provider != null ) {
-            this.provider.start(context);
+        this.activationCount++;
+        if ( this.provider == null ) {
+            this.provider = (ResourceProvider<Object>) this.bundleContext.getService(this.info.getServiceReference());
+            if ( this.provider != null ) {
+                this.provider.start(context);
+            }
         }
         return this.provider != null;
     }
 
-    /**C
+    public void deactivate() {
+        if ( this.provider != null ) {
+            this.provider.stop();
+            this.provider = null;
+            this.context.update(null, null);
+            this.bundleContext.ungetService(this.info.getServiceReference());
+        }
+    }
+
+    /**
      * Clear all references.
      */
     public void dispose() {
@@ -66,6 +80,10 @@ public class ResourceProviderHandler imp
         this.isUsed = false;
     }
 
+    public long getActivationCount() {
+        return this.activationCount;
+    }
+
     public ResourceProvider<Object> getResourceProvider() {
         return this.provider;
     }
@@ -79,15 +97,6 @@ public class ResourceProviderHandler imp
         return this.isUsed;
     }
 
-    public void deactivate() {
-        if ( this.provider != null ) {
-            this.provider.stop();
-            this.provider = null;
-            this.context.update(null, null);
-            this.bundleContext.ungetService(this.info.getServiceReference());
-        }
-    }
-
     @Override
     public int compareTo(final ResourceProviderHandler o) {
         if ( this.getInfo() == null ) {

Modified: sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTracker.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTracker.java?rev=1736182&r1=1736181&r2=1736182&view=diff
==============================================================================
--- sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTracker.java (original)
+++ sling/trunk/bundles/resourceresolver/src/main/java/org/apache/sling/resourceresolver/impl/providers/ResourceProviderTracker.java Tue Mar 22 10:52:16 2016
@@ -163,6 +163,10 @@ public class ResourceProviderTracker imp
         if ( info.isValid() ) {
            logger.debug("Registering new resource provider {}", info);
            final List<ProviderEvent> events = new ArrayList<ResourceProviderTracker.ProviderEvent>();
+           boolean providerAdded = false;
+           ResourceProviderHandler deactivateHandler = null;
+           long deactivateHandlerCount = 0;
+
            synchronized ( this.handlers ) {
                List<ResourceProviderHandler> matchingHandlers = this.handlers.get(info.getPath());
                if ( matchingHandlers == null ) {
@@ -179,26 +183,36 @@ public class ResourceProviderTracker imp
                            this.handlers.remove(info.getPath());
                        }
                    } else {
-                       final ChangeListener cl = this.listener;
-                       if ( cl != null ) {
-                           cl.providerAdded();
-                       }
+                       providerAdded = true;
                        events.add(new ProviderEvent(true, info));
                        if ( matchingHandlers.size() > 1 ) {
-                           final ResourceProviderHandler removeHandler = matchingHandlers.get(1);
-                           final ResourceProviderInfo removeInfo = removeHandler.getInfo();
-                           if ( cl != null ) {
-                               cl.providerRemoved((String)removeInfo.getServiceReference().getProperty(Constants.SERVICE_PID),
-                                       removeInfo.getAuthType() != AuthType.no,
-                                       removeHandler.isUsed());
-                           }
-                           this.deactivate(removeHandler);
-                           events.add(new ProviderEvent(false, removeInfo));
+                           deactivateHandler = matchingHandlers.get(1);
+                           deactivateHandlerCount = deactivateHandler.getActivationCount();
                        }
+                       storage = null;
+                   }
+               }
+           }
+           final ChangeListener cl = this.listener;
+           if ( providerAdded && cl != null ) {
+               cl.providerAdded();
+           }
+           // we have to check for deactivated handlers
+           if ( deactivateHandler != null ) {
+               final ResourceProviderInfo handlerInfo = deactivateHandler.getInfo();
+               if ( cl != null ) {
+                   cl.providerRemoved((String)handlerInfo.getServiceReference().getProperty(Constants.SERVICE_PID),
+                               handlerInfo.getAuthType() != AuthType.no,
+                                       deactivateHandler.isUsed());
+               }
+               synchronized ( this.handlers ) {
+                   if ( deactivateHandlerCount == deactivateHandler.getActivationCount() ) {
+                       this.deactivate(deactivateHandler);
+                       events.add(new ProviderEvent(false, handlerInfo));
+                       storage = null;
                    }
                }
            }
-           this.storage = null;
            this.postEvents(events);
         } else {
             logger.warn("Ignoring invalid resource provider {}", info);
@@ -219,31 +233,39 @@ public class ResourceProviderTracker imp
         if ( !isInvalid ) {
             logger.debug("Unregistering resource provider {}", info);
             final List<ProviderEvent> events = new ArrayList<ResourceProviderTracker.ProviderEvent>();
+            ResourceProviderHandler deactivateHandler = null;
             synchronized (this.handlers) {
                 final List<ResourceProviderHandler> matchingHandlers = this.handlers.get(info.getPath());
                 if ( matchingHandlers != null ) {
-                    boolean doActivateNext = false;
                     final ResourceProviderHandler firstHandler = matchingHandlers.get(0);
                     if ( firstHandler.getInfo() == info ) {
-                        doActivateNext = true;
-                        final ChangeListener cl = this.listener;
-                        if ( cl != null ) {
-                            cl.providerRemoved(pid,
-                                    info.getAuthType() != AuthType.no,
-                                    firstHandler.isUsed());
-                        }
-                        this.deactivate(firstHandler);
-                        events.add(new ProviderEvent(false, firstHandler.getInfo()));
+                        deactivateHandler = firstHandler;
+
                     }
+                }
+            }
+            if ( deactivateHandler != null ) {
+                final ChangeListener cl = this.listener;
+                if ( cl != null ) {
+                    cl.providerRemoved(pid,
+                            info.getAuthType() != AuthType.no,
+                                    deactivateHandler.isUsed());
+                }
+                boolean providerAdded = false;
+                synchronized ( this.handlers ) {
+                    this.deactivate(deactivateHandler);
+                    storage = null;
+
+                    final List<ResourceProviderHandler> matchingHandlers = this.handlers.get(info.getPath());
+                    final ResourceProviderHandler firstHandler = matchingHandlers.get(0);
+                    boolean doActivateNext = firstHandler.getInfo() == info;
+
                     if (removeHandlerByInfo(info, matchingHandlers)) {
                         while (doActivateNext && !matchingHandlers.isEmpty()) {
                             if (this.activate(matchingHandlers.get(0))) {
                                 doActivateNext = false;
                                 events.add(new ProviderEvent(true, matchingHandlers.get(0).getInfo()));
-                                final ChangeListener cl = this.listener;
-                                if ( cl != null ) {
-                                    cl.providerAdded();
-                                }
+                                providerAdded = true;
                             } else {
                                 matchingHandlers.remove(0);
                             }
@@ -253,8 +275,14 @@ public class ResourceProviderTracker imp
                         this.handlers.remove(info.getPath());
                     }
                 }
+                if ( providerAdded && cl != null ) {
+                    if ( cl != null ) {
+                        cl.providerAdded();
+                    }
+                }
+                events.add(new ProviderEvent(false,info));
+
             }
-            storage = null;
             this.postEvents(events);
         } else {
             logger.debug("Unregistering invalid resource provider {}", info);