Avoid a deadlock when updating the service properties.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1083701 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
index f9f0643..38e5697 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
@@ -327,41 +327,66 @@
      * service.
      * This method also notifies the creation strategy of the publication.
      */
-    protected synchronized void registerService() {
-        // Unregister if registered
-        if (m_serviceRegistration != null) {
-            unregisterService();
+    protected void registerService() {
+        ServiceRegistration reg = null;
+        Properties serviceProperties = null;
+
+        synchronized (this) {
+            // Unregister if registered
+            if (m_serviceRegistration != null) {
+                unregisterService();
+            }
+
+            if (m_handler.getInstanceManager().getState() == ComponentInstance.VALID
+                    && m_serviceRegistration == null
+                    && isAtLeastAServiceControllerValid()) {
+                // Build the service properties list
+
+                BundleContext bc = m_handler.getInstanceManager().getContext();
+                // Security check
+                if (SecurityHelper.hasPermissionToRegisterServices(
+                        m_serviceSpecifications, bc)) {
+                    serviceProperties = getServiceProperties();
+                    m_strategy.onPublication(getInstanceManager(),
+                            getServiceSpecificationsToRegister(),
+                            serviceProperties);
+                    m_serviceRegistration = bc.registerService(
+                            getServiceSpecificationsToRegister(), this,
+                            serviceProperties);
+                    reg = m_serviceRegistration; // Stack confinement
+                } else {
+                    throw new SecurityException("The bundle "
+                            + bc.getBundle().getBundleId()
+                            + " does not have the"
+                            + " permission to register the services "
+                            + Arrays.asList(m_serviceSpecifications));
+                }
+            }
         }
 
-        if (m_handler.getInstanceManager().getState() == ComponentInstance.VALID
-                && m_serviceRegistration == null  && isAtLeastAServiceControllerValid()) {
-            // Build the service properties list
+        // An update may happen during the registration, re-check and apply.
+        // This must be call outside the synchronized block.
+        if (reg != null && m_wasUpdated) {
+            reg.setProperties(getServiceProperties());
+            m_wasUpdated = false;
+        }
 
-            BundleContext bc = m_handler.getInstanceManager().getContext();
-            // Security check
-            if (SecurityHelper.hasPermissionToRegisterServices(m_serviceSpecifications, bc)) {
-                Properties serviceProperties = getServiceProperties();
-                m_strategy.onPublication(getInstanceManager(), getServiceSpecificationsToRegister(), serviceProperties);
-                m_serviceRegistration = bc.registerService(getServiceSpecificationsToRegister(), this, serviceProperties);
-                // An update may happen during the registration, re-check and apply.
-                if (m_wasUpdated) {
-                    m_serviceRegistration.setProperties(getServiceProperties());
-                    m_wasUpdated = false;
+        synchronized (this) {
+            // Call the post-registration callback in the same thread holding
+            // the monitor lock.
+            // This allows to be sure that the callback is called once per
+            // registration.
+            // But the callback must take care to not create a deadlock
+            if (m_postRegistration != null) {
+                try {
+                    m_postRegistration
+                            .call(new Object[] { m_serviceRegistration
+                                    .getReference() });
+                } catch (Exception e) {
+                    m_handler.error(
+                            "Cannot invoke the post-registration callback "
+                                    + m_postRegistration.getMethod(), e);
                 }
-
-                // Call the post-registration callback in the same thread holding the monitor lock.
-                // This allows to be sure that the callback is called once per registration.
-                // But the callback must take care to not create a deadlock
-                if (m_postRegistration != null) {
-	                try {
-						m_postRegistration.call(new Object[] { m_serviceRegistration.getReference() });
-					} catch (Exception e) {
-						m_handler.error("Cannot invoke the post-registration callback " + m_postRegistration.getMethod(), e);
-					}
-                }
-            } else {
-                throw new SecurityException("The bundle " + bc.getBundle().getBundleId() + " does not have the"
-                        + " permission to register the services " + Arrays.asList(m_serviceSpecifications));
             }
         }
     }
@@ -370,12 +395,12 @@
      * Unregisters the service.
      */
     protected synchronized void unregisterService() {
-    	// Create a copy of the service reference in the case we need
-    	// to inject it to the post-unregistration callback.
+        // Create a copy of the service reference in the case we need
+        // to inject it to the post-unregistration callback.
 
-    	ServiceReference ref = null;
+        ServiceReference ref = null;
         if (m_serviceRegistration != null) {
-    		ref = m_serviceRegistration.getReference();
+            ref = m_serviceRegistration.getReference();
             m_serviceRegistration.unregister();
             m_serviceRegistration = null;
         }
@@ -387,10 +412,10 @@
         // But the callback must take care to not create a deadlock
         if (m_postUnregistration != null   && ref != null) {
             try {
-            	m_postUnregistration.call(new Object[] { ref });
-			} catch (Exception e) {
-				m_handler.error("Cannot invoke the post-unregistration callback " + m_postUnregistration.getMethod(), e);
-			}
+                m_postUnregistration.call(new Object[] { ref });
+            } catch (Exception e) {
+                m_handler.error("Cannot invoke the post-unregistration callback " + m_postUnregistration.getMethod(), e);
+            }
         }
 
     }
@@ -587,14 +612,14 @@
     }
 
     public void setPostRegistrationCallback(Callback cb) {
-		m_postRegistration = cb;
-	}
+        m_postRegistration = cb;
+    }
 
     public void setPostUnregistrationCallback(Callback cb) {
-		m_postUnregistration = cb;
-	}
+        m_postUnregistration = cb;
+    }
 
-	/**
+    /**
      * Service Controller.
      */
     class ServiceController {