You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pd...@apache.org on 2010/08/16 17:41:19 UTC

svn commit: r985994 - /felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServicePublisher.java

Author: pderop
Date: Mon Aug 16 15:41:19 2010
New Revision: 985994

URL: http://svn.apache.org/viewvc?rev=985994&view=rev
Log:
fixed a potential race condition in the Service annotation, where a publisher may be invoked before the component is actually started

Modified:
    felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServicePublisher.java

Modified: felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServicePublisher.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServicePublisher.java?rev=985994&r1=985993&r2=985994&view=diff
==============================================================================
--- felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServicePublisher.java (original)
+++ felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServicePublisher.java Mon Aug 16 15:41:19 2010
@@ -93,28 +93,81 @@ public class ServicePublisher
                   .setDefaultImplementation(unpublisher));
         }
     }
-
+    
+    private void publish() 
+    {
+        if (m_published.compareAndSet(false, true))
+        {
+            try
+            {
+                Log.instance().log(LogService.LOG_DEBUG, "publishing services %s",
+                                   Arrays.toString(m_services));
+                m_registration = m_bc.registerService(m_services, m_srv.getService(), m_srv.getServiceProperties());
+            }
+            catch (Throwable t)
+            {
+                if (t instanceof RuntimeException)
+                {
+                    throw (RuntimeException) t;
+                }
+                else
+                {
+                    throw new RuntimeException("Could not register services", t);
+                }
+            }
+        }
+    }
+    
+    private void unpublish()
+    {
+        if (m_published.compareAndSet(true, false))
+        {
+            try
+            {
+                if (m_registration != null) 
+                {
+                    Log.instance().log(LogService.LOG_DEBUG, "unpublishing services %s",
+                                       Arrays.toString(m_services));
+                    m_registration.unregister();
+                    m_registration = null;
+                }
+            }
+            catch (Throwable t)
+            {
+                if (t instanceof RuntimeException)
+                {
+                    throw (RuntimeException) t;
+                }
+                else
+                {
+                    throw new RuntimeException("Could not unregister services", t);
+                }
+            }
+        }
+    }
+     
     private class Publisher implements Runnable, ServiceStateListener
     {
-        private boolean m_started; // true if the service has started
-        
+        // true if the service has started
+        private boolean m_started; 
+        // flag used to delay early publisher until we are really started.
+        public boolean m_publishDelayed; 
+
         public void run()
         {
-            if (m_published.compareAndSet(false, true))
-            {
-                // Only register the service if it has been started. Otherwise delay the registration
-                // until the service start callback has been invoked.
-                synchronized (this) {
-                    if (! m_started)
-                    {
-                        Log.instance().log(LogService.LOG_DEBUG, "Delaying service publication for services %s (service not yet started)",
-                                           Arrays.toString(m_services));
+            // Only register the service if it has been started. Otherwise delay the registration
+            // until the service start callback has been invoked.
+            synchronized (this) {
+                if (! m_started)
+                {
+                    Log.instance().log(LogService.LOG_DEBUG, "Delaying service publication for services %s (service not yet started)",
+                                       Arrays.toString(m_services));
 
-                        return;
-                    }
+                    m_publishDelayed = true;       
+                    return;
                 }
-                publish();
             }
+            publish();
         }
 
         public void starting(Service service)
@@ -123,11 +176,16 @@ public class ServicePublisher
 
         public void started(Service service)
         {
+            boolean publishDelayed = false;
             synchronized (this)
             {
                 m_started = true;
+                if (m_publishDelayed) 
+                {
+                    publishDelayed = true;
+                }
             }
-            if (m_published.get())
+            if (publishDelayed)
             {
                 // Our runnable has been invoked before the service start callback has been called: 
                 // Now that we are started, we fire the service registration.
@@ -140,62 +198,21 @@ public class ServicePublisher
             synchronized (this)
             {
                 m_started = false;
+                m_publishDelayed = false;
             }
-
-            if (m_published.compareAndSet(true, false))
-            {
-                if (m_registration != null)
-                {
-                    Log.instance().log(LogService.LOG_DEBUG, "unpublishing services %s (service is stopping)",
-                                       Arrays.toString(m_services));
-
-                    m_registration.unregister();
-                    m_registration = null;
-                }
-            }
+            unpublish();
         }
 
         public void stopped(Service service)
         {
-        }
-        
-        private void publish()
-        {
-            try
-            {
-                Log.instance().log(LogService.LOG_DEBUG, "publishing services %s",
-                                   Arrays.toString(m_services));
-                m_registration = m_bc.registerService(m_services, m_srv.getService(), m_srv.getServiceProperties());
-            }
-            catch (Throwable t)
-            {
-                m_published.set(false);
-                if (t instanceof RuntimeException)
-                {
-                    throw (RuntimeException) t;
-                }
-                else
-                {
-                    throw new RuntimeException("Could not register services", t);
-                }
-            }
-        }
+        }        
     }
 
     private class Unpublisher implements Runnable
     {
         public void run()
         {
-            if (m_published.compareAndSet(true, false))
-            {
-                if (m_registration != null)
-                {
-                    Log.instance().log(LogService.LOG_DEBUG, "unpublishing services %s",
-                                       Arrays.toString(m_services));
-                    m_registration.unregister();
-                    m_registration = null;
-                }
-            }
+            unpublish();
         }
     }
 }