incubator-aries-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mahrw...@apache.org
Subject svn commit: r990084 - in /incubator/aries/trunk/blueprint: blueprint-core/src/main/java/org/apache/aries/blueprint/container/ blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/ blueprint-sample/src/main/java/org/apache/aries/blueprint/sa...
Date Fri, 27 Aug 2010 10:21:00 GMT
Author: mahrwald
Date: Fri Aug 27 10:20:59 2010
New Revision: 990084

URL: http://svn.apache.org/viewvc?rev=990084&view=rev
Log:
ARIES 390: Small scale fix for merge back to 0.2 release branch

Added:
    incubator/aries/trunk/blueprint/blueprint-sample/src/main/java/org/apache/aries/blueprint/sample/DodgyListener.java
Modified:
    incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ServiceRecipe.java
    incubator/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/BlueprintContainerTest.java
    incubator/aries/trunk/blueprint/blueprint-sample/src/main/resources/OSGI-INF/blueprint/config.xml

Modified: incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ServiceRecipe.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ServiceRecipe.java?rev=990084&r1=990083&r2=990084&view=diff
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ServiceRecipe.java
(original)
+++ incubator/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/ServiceRecipe.java
Fri Aug 27 10:20:59 2010
@@ -25,6 +25,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.aries.blueprint.BlueprintConstants;
 import org.apache.aries.blueprint.ExtendedBlueprintContainer;
@@ -65,7 +66,7 @@ public class ServiceRecipe extends Abstr
 
     private Map properties;
     private final AtomicBoolean registered = new AtomicBoolean();
-    private volatile ServiceRegistration registration;
+    private final AtomicReference<ServiceRegistration> registration = new AtomicReference<ServiceRegistration>();
     private Map registrationProperties;
     private List<ServiceListener> listeners;
     private volatile Object service;
@@ -162,7 +163,7 @@ public class ServiceRecipe extends Abstr
             LOGGER.debug("Registering service {} with interfaces {} and properties {}",
                          new Object[] { name, classes, props });
 
-            registration = blueprintContainer.registerService(classArray, new TriggerServiceFactory(),
props);            
+            registration.set(blueprintContainer.registerService(classArray, new TriggerServiceFactory(),
props));            
         }
     }
 
@@ -171,7 +172,7 @@ public class ServiceRecipe extends Abstr
             LOGGER.debug("Unregistering service {}", name);
             // This method needs to allow reentrance, so if we need to make sure the registration
is
             // set to null before actually unregistering the service
-            ServiceRegistration reg = registration;
+            ServiceRegistration reg = registration.get();
             if (listeners != null) {
                 LOGGER.debug("Calling listeners for service unregistration");
                 for (ServiceListener listener : listeners) {
@@ -181,26 +182,26 @@ public class ServiceRecipe extends Abstr
             if (reg != null) {
                 reg.unregister();
             }
-            // We need to do this hack in order to support reantrancy
-            if (registration == reg) {
-                registration = null;
-            }
+            
+            registration.compareAndSet(reg, null);
         }
     }
 
     protected ServiceReference getReference() {
-        if (registration == null) {
+    	ServiceRegistration reg = registration.get();
+        if (reg == null) {
             throw new IllegalStateException("Service is not registered");
         } else {
-            return registration.getReference();
+            return reg.getReference();
         }
     }
 
     protected void setProperties(Dictionary props) {
-        if (registration == null) {
+    	ServiceRegistration reg = registration.get();
+        if (reg == null) {
             throw new IllegalStateException("Service is not registered");
         } else {
-            registration.setProperties(props);
+            reg.setProperties(props);
             // TODO: set serviceProperties? convert somehow? should listeners be notified
of this?
         }
     }
@@ -230,24 +231,26 @@ public class ServiceRecipe extends Abstr
                 }
             }
         }
+        
         Object service = this.service;
         // We need the real service ...
         if (bundle != null) {
-            if (service instanceof ServiceFactory) {
-                service = ((ServiceFactory) service).getService(bundle, registration);
-            }
-            if (service == null) {
-                throw new IllegalStateException("service is null");
-            }
-            // Check if the service actually implement all the requested interfaces
-            validateClasses(service);
-        // We're not really interested in the service, but perform some sanity checks nonetheless
+        	if (service instanceof ServiceFactory) {
+        		service = ((ServiceFactory) service).getService(bundle, registration);
+        	}
+        	if (service == null) {
+        		throw new IllegalStateException("service is null");
+        	}
+        	// Check if the service actually implement all the requested interfaces
+        	validateClasses(service);
+        	// We're not really interested in the service, but perform some sanity checks nonetheless
         } else {
-             if (!(service instanceof ServiceFactory)) {
-                 // Check if the service actually implement all the requested interfaces
-                 validateClasses(service);
-             }
+        	if (!(service instanceof ServiceFactory)) {
+        		// Check if the service actually implement all the requested interfaces
+        		validateClasses(service);
+        	}
         }
+        
         return service;
     }
 
@@ -297,18 +300,16 @@ public class ServiceRecipe extends Abstr
         }
     }
 
-    public synchronized Object getService(Bundle bundle, ServiceRegistration registration)
{
+    public Object getService(Bundle bundle, ServiceRegistration registration) {
         /** getService() can get called before registerService() returns with the registration
object.
          *  So we need to set the registration object in case registration listeners call

          *  getServiceReference(). 
          */
-        if (this.registration == null) {
-            this.registration = registration;
-        }
+    	this.registration.compareAndSet(null, registration);
         return internalGetService(bundle, registration);
     }
 
-    public synchronized void ungetService(Bundle bundle, ServiceRegistration registration,
Object service) {
+    public void ungetService(Bundle bundle, ServiceRegistration registration, Object service)
{
         if (this.service instanceof ServiceFactory) {
             ((ServiceFactory) this.service).ungetService(bundle, registration, service);
         }

Modified: incubator/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/BlueprintContainerTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/BlueprintContainerTest.java?rev=990084&r1=990083&r2=990084&view=diff
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/BlueprintContainerTest.java
(original)
+++ incubator/aries/trunk/blueprint/blueprint-itests/src/test/java/org/apache/aries/blueprint/itests/BlueprintContainerTest.java
Fri Aug 27 10:20:59 2010
@@ -31,6 +31,7 @@ import static org.ops4j.pax.exam.CoreOpt
 import java.text.SimpleDateFormat;
 import java.util.Currency;
 import java.util.Hashtable;
+import java.util.HashSet;
 
 import org.apache.aries.blueprint.sample.Bar;
 import org.apache.aries.blueprint.sample.Foo;
@@ -63,6 +64,20 @@ public class BlueprintContainerTest exte
         // do the test
         testBlueprintContainer(bundle);
     }
+    
+    @Test
+    public void testDeadlock() throws Exception {
+      bundleContext.registerService("java.util.Set",new HashSet<Object>(), null);
+      
+      Bundle bundle = getInstalledBundle("org.apache.aries.blueprint.sample");
+      assertNotNull(bundle);
+
+      bundle.start();
+      
+      getBlueprintContainerForBundle(bundleContext, "org.apache.aries.blueprint.sample",5000);
+      
+      // no actual assertions, we just don't want to deadlock
+    }
 
     @org.ops4j.pax.exam.junit.Configuration
     public static Option[] configuration() {

Added: incubator/aries/trunk/blueprint/blueprint-sample/src/main/java/org/apache/aries/blueprint/sample/DodgyListener.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-sample/src/main/java/org/apache/aries/blueprint/sample/DodgyListener.java?rev=990084&view=auto
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-sample/src/main/java/org/apache/aries/blueprint/sample/DodgyListener.java
(added)
+++ incubator/aries/trunk/blueprint/blueprint-sample/src/main/java/org/apache/aries/blueprint/sample/DodgyListener.java
Fri Aug 27 10:20:59 2010
@@ -0,0 +1,54 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.aries.blueprint.sample;
+
+import java.util.Set;
+import java.util.Map;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public class DodgyListener {
+  private BundleContext ctx;
+  
+  public void setBundleContext(BundleContext ctx) {
+    this.ctx = ctx;
+  }
+  
+  public void bind(Set a, Map props) {
+    System.out.println("Attempting to provoke deadlock");
+    
+    Thread t = new Thread() {
+      public void run() {
+    	// we pretend to be another bundle (otherwise we'll deadlock in Equinox itself :(
+    	BundleContext otherCtx = ctx.getBundle(0).getBundleContext();  
+    	  
+        ServiceReference ref = otherCtx.getServiceReference("java.util.List");
+        otherCtx.getService(ref);
+      }
+    };
+    t.start();
+    
+    // let the other thread go first
+    try {
+      Thread.sleep(100);
+    } catch (Exception e) {}
+    
+    ServiceReference ref = ctx.getServiceReference("java.util.List");
+    ctx.getService(ref);
+  }
+}
\ No newline at end of file

Modified: incubator/aries/trunk/blueprint/blueprint-sample/src/main/resources/OSGI-INF/blueprint/config.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/blueprint/blueprint-sample/src/main/resources/OSGI-INF/blueprint/config.xml?rev=990084&r1=990083&r2=990084&view=diff
==============================================================================
--- incubator/aries/trunk/blueprint/blueprint-sample/src/main/resources/OSGI-INF/blueprint/config.xml
(original)
+++ incubator/aries/trunk/blueprint/blueprint-sample/src/main/resources/OSGI-INF/blueprint/config.xml
Fri Aug 27 10:20:59 2010
@@ -118,8 +118,38 @@
 		<reference-listener bind-method="bind"
 			unbind-method="unbind" ref="listBindingListener" />
 	</reference-list>
-
+	
 	<bean id="listBindingListener" class="org.apache.aries.blueprint.sample.BindingListener"
/>
+	
+	
+	
+	<!-- Deadlock setup 
+	  We have a lazily activated service (i.e. register the service but don't create it yet)
+	  Then we have a reference-listener (or some other piece of client code that is called while
instantiating blueprint components)
+	  
+	  This then tries to obtain the initial service twice:
+	  - first from a new thread
+	  - second from the current thread (that is creating blueprint components)
+	  
+	  This is of course contrived. However, any other piece of code may be substituted for the
first thread and with unlucky
+	  timing we get into the same deadlock situation.
+	-->
+	
+	<service interface="java.util.List" activation="lazy">
+	  <bean class="java.util.ArrayList" />
+	</service>
+	
+	<bean id="dodgyListener" class="org.apache.aries.blueprint.sample.DodgyListener">
+	  <property name="bundleContext" ref="blueprintBundleContext" />
+	</bean>
+	
+	<reference-list interface="java.util.Set" availability="optional">
+	  <reference-listener bind-method="bind" ref="dodgyListener" />
+	</reference-list>
+
+
+
+
 
 	<bean id="circularReference" class="org.apache.aries.blueprint.sample.BindingListener"
 		init-method="init">



Mime
View raw message