You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by da...@apache.org on 2015/06/11 21:13:17 UTC

svn commit: r1684963 - in /felix/trunk/framework/src: main/java/org/apache/felix/framework/ServiceRegistry.java test/java/org/apache/felix/framework/ServiceRegistryTest.java

Author: davidb
Date: Thu Jun 11 19:13:17 2015
New Revision: 1684963

URL: http://svn.apache.org/r1684963
Log:
FELIX-4866 Improve Service Registry

The previous code that was contributed as part of FELIX-4866 could cause ungetService() on a Service Factory to be called with a null service object. This change fixes that.

Modified:
    felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
    felix/trunk/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java?rev=1684963&r1=1684962&r2=1684963&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java Thu Jun 11 19:13:17 2015
@@ -417,26 +417,37 @@ public class ServiceRegistry
             int count = usage.m_count.decrementAndGet();
             try
             {
-                if (count == 0)
+                if (count <= 0)
                 {
-                    ServiceHolder holder = usage.m_svcHolderRef.getAndSet(null);
+                    ServiceHolder holder = usage.m_svcHolderRef.get();
                     Object svc = holder != null ? holder.m_service : null;
 
-                    // Remove reference from usages array.
-                    ((ServiceRegistrationImpl.ServiceReferenceImpl) ref)
-                        .getRegistration().ungetService(bundle, svc);
+                    if (svc != null)
+                    {
+                        if (usage.m_svcHolderRef.compareAndSet(holder, null))
+                        {
+                            holder.m_service = null;
+
+                            // Remove reference from usages array.
+                            ((ServiceRegistrationImpl.ServiceReferenceImpl) ref)
+                                .getRegistration().ungetService(bundle, svc);
+
+                        }
+
+                    }
                 }
             }
             finally
             {
-                // Finally, decrement usage count and flush if it goes to zero or
-                // the registration became invalid.
+                if (!reg.isValid())
+                {
+                    usage.m_svcHolderRef.set(null);
+                }
 
                 // If the registration is invalid or the usage count has reached
                 // zero, then flush it.
-                if ((count <= 0) || !reg.isValid())
+                if (count <= 0 || !reg.isValid())
                 {
-                    usage.m_svcHolderRef.set(null);
                     flushUsageCount(bundle, ref, usage);
                 }
             }

Modified: felix/trunk/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java?rev=1684963&r1=1684962&r2=1684963&view=diff
==============================================================================
--- felix/trunk/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java (original)
+++ felix/trunk/framework/src/test/java/org/apache/felix/framework/ServiceRegistryTest.java Thu Jun 11 19:13:17 2015
@@ -526,7 +526,10 @@ public class ServiceRegistryTest extends
                 (ConcurrentMap<Bundle, UsageCount[]>) getPrivateField(sr, "m_inUseMap");
 
         UsageCount uc = new UsageCount(ref, false);
-        uc.m_svcHolderRef.set(new ServiceHolder());
+        ServiceHolder sh = new ServiceHolder();
+        Object svc = new Object();
+        sh.m_service = svc;
+        uc.m_svcHolderRef.set(sh);
         uc.m_count.incrementAndGet();
 
         Mockito.verify(reg, Mockito.never()).
@@ -538,7 +541,7 @@ public class ServiceRegistryTest extends
         assertNull(inUseMap.get(b));
 
         Mockito.verify(reg, Mockito.times(1)).
-        ungetService(Mockito.isA(Bundle.class), Mockito.any());
+            ungetService(Mockito.isA(Bundle.class), Mockito.eq(svc));
     }
 
     @SuppressWarnings("unchecked")