You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by dj...@apache.org on 2013/04/22 08:44:25 UTC

svn commit: r1470394 - in /felix/trunk/scr: ./ src/main/java/org/apache/felix/scr/ src/main/java/org/apache/felix/scr/impl/ src/main/java/org/apache/felix/scr/impl/manager/ src/test/java/org/apache/felix/scr/impl/manager/

Author: djencks
Date: Mon Apr 22 06:44:24 2013
New Revision: 1470394

URL: http://svn.apache.org/r1470394
Log:
FELIX-4020 fix a several locking problems and bugs in modifiedService customizer methods, add thread dumps, reset interrrupt flag on interrupedException, rename open to prebind to reduce confusion with open(S) method

Modified:
    felix/trunk/scr/pom.xml
    felix/trunk/scr/src/main/java/org/apache/felix/scr/Component.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentActorThread.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/EdgeInfo.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/RegistrationManager.java
    felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/RegistrationManagerTest.java

Modified: felix/trunk/scr/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/scr/pom.xml?rev=1470394&r1=1470393&r2=1470394&view=diff
==============================================================================
--- felix/trunk/scr/pom.xml (original)
+++ felix/trunk/scr/pom.xml Mon Apr 22 06:44:24 2013
@@ -380,7 +380,7 @@
                         <exclude>**/components/**</exclude>
                     </excludes>
                     <includes>
-                        <include>**/integration/*</include>
+                        <include>**/integration/**</include>
                     </includes>
                 </configuration>
             </plugin>

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/Component.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/Component.java?rev=1470394&r1=1470393&r2=1470394&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/Component.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/Component.java Mon Apr 22 06:44:24 2013
@@ -73,8 +73,8 @@ public interface Component
     /**
      * The Component has successfully been activated and is fully functional
      * (value is 16). This is the state of immediate components after
-     * successfull activation. Delayed and Service Factory Components enter
-     * this state when the service instance has actually be instantiated because
+     * successful activation. Delayed and Service Factory Components enter
+     * this state when the service instance has actually been instantiated because
      * the service has been acquired.
      */
     static final int STATE_ACTIVE = 16;

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentActorThread.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentActorThread.java?rev=1470394&r1=1470393&r2=1470394&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentActorThread.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentActorThread.java Mon Apr 22 06:44:24 2013
@@ -127,6 +127,7 @@ class ComponentActorThread implements Ru
                 }
                 catch ( InterruptedException e )
                 {
+                    Thread.currentThread().interrupt();
                     Activator.log( LogService.LOG_ERROR, null, "Interrupted exception waiting for queue to empty", e );
                 }
             }

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java?rev=1470394&r1=1470393&r2=1470394&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java Mon Apr 22 06:44:24 2013
@@ -186,6 +186,7 @@ public abstract class AbstractComponentM
         }
         catch ( InterruptedException e )
         {
+            Thread.currentThread().interrupt();
             //TODO this is so wrong
             throw new IllegalStateException( "Could not obtain lock (Reason: " + e + ")" );
         }
@@ -211,7 +212,7 @@ public abstract class AbstractComponentM
         return m_stateLock.getHoldCount() > 0;
     }
     
-    private void dumpThreads()
+    void dumpThreads()
     {
         try
         {
@@ -270,6 +271,7 @@ public abstract class AbstractComponentM
                     {
                         log( LogService.LOG_ERROR, "waitForTracked timed out: {0} ceiling: {1} missing: {2},  Expect further errors",
                                 new Object[] {trackingCount, ceiling, missing}, null );
+                        dumpThreads();
                         missing.clear();
                         return;
                         
@@ -277,7 +279,7 @@ public abstract class AbstractComponentM
                 }
                 catch ( InterruptedException e )
                 {
-                    //??
+                    Thread.currentThread().interrupt();
                 }
             }
         }
@@ -356,7 +358,7 @@ public abstract class AbstractComponentM
         }
         catch ( InterruptedException e )
         {
-            //??
+            Thread.currentThread().interrupt();
         }
         finally
         {
@@ -430,7 +432,7 @@ public abstract class AbstractComponentM
         }
         catch ( InterruptedException e )
         {
-            //??
+            Thread.currentThread().interrupt();
         }
         finally
         {
@@ -776,6 +778,12 @@ public abstract class AbstractComponentM
         {
             return getLockTimeout();
         }
+
+        @Override
+        void reportTimeout()
+        {
+            dumpThreads();
+        }
         
     };
     

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java?rev=1470394&r1=1470393&r2=1470394&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java Mon Apr 22 06:44:24 2013
@@ -187,6 +187,7 @@ public class ComponentContextImpl<S> imp
         }
         catch ( InterruptedException e )
         {
+            Thread.currentThread().interrupt();
             return null;
         }
         return null;

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java?rev=1470394&r1=1470393&r2=1470394&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java Mon Apr 22 06:44:24 2013
@@ -32,6 +32,7 @@ import java.util.Map;
 import java.util.SortedMap;
 import java.util.TreeMap;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -125,7 +126,12 @@ public class DependencyManager<S, T> imp
 
     private interface Customizer<T> extends ServiceTrackerCustomizer<T, RefPair<T>>
     {
-        boolean open();
+        /**
+         * attempt to obtain the services from the tracked service references that will be used in inital bind calls
+         * before activation.
+         * @return true if there are enough services for activation.
+         */
+        boolean prebind();
 
         void close();
 
@@ -263,7 +269,7 @@ public class DependencyManager<S, T> imp
             }
         }
 
-        public boolean open()
+        public boolean prebind()
         {
             boolean success = m_dependencyMetadata.isOptional() || !getTracker().isEmpty();
             AtomicInteger trackingCount = new AtomicInteger( );
@@ -294,10 +300,6 @@ public class DependencyManager<S, T> imp
             {
                 refPair = new RefPair<T>( serviceReference  );
             }
-            if (isActive())
-            {
-                 getServiceObject( m_bindMethods.getBind(), refPair );
-            }
             return refPair;
         }
 
@@ -309,6 +311,7 @@ public class DependencyManager<S, T> imp
             {
                 if (isActive())
                 {
+                    getServiceObject( m_bindMethods.getBind(), refPair );
                     if ( !refPair.isFailed() )
                     {
                         m_componentManager.invokeBindMethod( DependencyManager.this, refPair, trackingCount );
@@ -372,7 +375,7 @@ public class DependencyManager<S, T> imp
             ungetService( refPair );
         }
 
-        public boolean open()
+        public boolean prebind()
         {
             boolean success = m_dependencyMetadata.isOptional();
             AtomicInteger trackingCount = new AtomicInteger( );
@@ -487,7 +490,7 @@ public class DependencyManager<S, T> imp
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticGreedy removed {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
         }
 
-        public boolean open()
+        public boolean prebind()
         {
             boolean success = m_dependencyMetadata.isOptional();
             AtomicInteger trackingCount = new AtomicInteger( );
@@ -497,6 +500,11 @@ public class DependencyManager<S, T> imp
                 synchronized (refPair)
                 {
                     success |= getServiceObject( m_bindMethods.getBind(), refPair );
+                    if ( refPair.isFailed() )
+                    {
+                        m_componentManager.registerMissingDependency( DependencyManager.this, refPair.getRef(),
+                                trackingCount.get() );
+                    }
                 }
             }
             return success;
@@ -547,8 +555,9 @@ public class DependencyManager<S, T> imp
         public void modifiedService( ServiceReference<T> serviceReference, RefPair<T> refPair, int trackingCount )
         {
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant modified {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
-            if (isActive())
-            {
+            Collection<RefPair<T>> refs = this.refs.get();
+            if (isActive() && refs.contains( refPair ))
+            {                
                 m_componentManager.invokeUpdatedMethod( DependencyManager.this, refPair, trackingCount );
             }
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant modified {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
@@ -579,7 +588,7 @@ public class DependencyManager<S, T> imp
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} MultipleStaticReluctant removed {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
         }
 
-        public boolean open()
+        public boolean prebind()
         {
             boolean success = m_dependencyMetadata.isOptional();
             Collection<RefPair<T>> refs = this.refs.get();
@@ -730,107 +739,115 @@ public class DependencyManager<S, T> imp
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic removed {2} (enter)", new Object[] {getName(), trackingCount, serviceReference}, null );
             boolean deactivate = false;
             boolean untracked = true;
+            RefPair<T> oldRefPair = null;
+            RefPair<T> nextRefPair = null;
             synchronized ( getTracker().tracked() )
             {
                 if ( refPair == this.refPair )
                 {
                     if ( isActive() )
                     {
-                        RefPair<T> nextRefPair = null;
                         if ( !getTracker().isEmpty() )
                         {
                             AtomicInteger trackingCount2 = new AtomicInteger();
                             SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true,
                                     trackingCount2 );
                             nextRefPair = tracked.values().iterator().next();
-                            synchronized ( nextRefPair )
-                            {
-                                if ( !getServiceObject( m_bindMethods.getBind(), nextRefPair ) )
-                                {
-                                    //TODO error???
-                                }
-                            }
-                            if ( !nextRefPair.isFailed() )
-                            {
-                                m_componentManager
-                                        .invokeBindMethod( DependencyManager.this, nextRefPair, trackingCount );
-                            }
                         }
-
                         if ( isOptional() || nextRefPair != null )
                         {
-                            RefPair<T> oldRefPair = this.refPair;
+                            oldRefPair = this.refPair;
                             this.refPair = null;
-                            this.trackingCount = trackingCount;
-                            m_componentManager.invokeUnbindMethod( DependencyManager.this, oldRefPair, trackingCount );
-                            this.refPair = nextRefPair;
-                            tracked( trackingCount );
-                            untracked = false;
-                            ungetService( oldRefPair );
                         }
-                        else
-                        //required and no replacement service, deactivate
+                        else 
                         {
-                            deactivate = true;
+                            deactivate = true;            //required and no replacement service, deactivate
                         }
                     }
-                    else
-                    //not active  This should not happen, close should have nulled this.refPair.
+                }
+            }
+            if ( nextRefPair != null )
+            {
+                synchronized ( nextRefPair )
+                {
+                    if ( !getServiceObject( m_bindMethods.getBind(), nextRefPair ) )
                     {
-                        this.refPair = null;
-                        this.trackingCount = trackingCount;
-                        tracked( trackingCount );
-                        untracked = false;
+                        //TODO error???
                     }
                 }
+                if ( !nextRefPair.isFailed() )
+                {
+                    m_componentManager.invokeBindMethod( DependencyManager.this, nextRefPair,
+                            trackingCount );
+                }
             }
-            if (untracked) // not ours
+
+            if ( oldRefPair != null )
             {
                 this.trackingCount = trackingCount;
+                m_componentManager.invokeUnbindMethod( DependencyManager.this, oldRefPair, trackingCount );
+                synchronized ( getTracker().tracked() )
+                {
+                    this.refPair = nextRefPair;
+                }
                 tracked( trackingCount );
+                untracked = false;
             }
-            if (deactivate)
+            else if ( deactivate )
             {
                 this.trackingCount = trackingCount;
                 tracked( trackingCount );
+                untracked = false;
                 m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE, false, trackingCount );
-
+            }
+            if ( oldRefPair != null )
+            {
+                ungetService( oldRefPair );
+            }
+            if (untracked) // not ours
+            {
+                this.trackingCount = trackingCount;
+                tracked( trackingCount );
             }
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleDynamic removed {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
         }
 
-        public boolean open()
+        public boolean prebind()
         {
+            RefPair<T> refPair = null;
             boolean success = m_dependencyMetadata.isOptional();
+            AtomicInteger trackingCount = new AtomicInteger();
             synchronized ( getTracker().tracked() )
             {
                 if ( success || !getTracker().isEmpty() )
                 {
-                    AtomicInteger trackingCount = new AtomicInteger();
                     SortedMap<ServiceReference<T>, RefPair<T>> tracked = getTracker().getTracked( true, trackingCount );
                     if ( !tracked.isEmpty() )
                     {
-                        RefPair<T> refPair = tracked.values().iterator().next();
-                        success |= getServiceObject( m_bindMethods.getBind(), refPair );
-                        if ( refPair.isFailed() )
-                        {
-                            m_componentManager.registerMissingDependency( DependencyManager.this, refPair.getRef(),
-                                    trackingCount.get() );
-                        }
+                        refPair = tracked.values().iterator().next();
                         this.refPair = refPair;
                     }
                 }
             }
+            if (refPair != null) 
+            {
+                synchronized( refPair )
+                {
+                    success |= getServiceObject( m_bindMethods.getBind(), refPair );
+                    if ( refPair.isFailed() )
+                    {
+                        m_componentManager.registerMissingDependency( DependencyManager.this, refPair.getRef(),
+                                trackingCount.get() );
+                    }
+                }
+            }
             return success;
         }
 
         public void close()
         {
-            synchronized ( getTracker().tracked() )
-            {
-                closeRefPair();
-                getTracker().deactivate();
-            }
+            closeRefPair();
+            getTracker().deactivate();
         }
 
         private void closeRefPair()
@@ -844,7 +861,7 @@ public class DependencyManager<S, T> imp
 
         public Collection<RefPair<T>> getRefs( AtomicInteger trackingCount )
         {
-            Object monitor = getTracker().tracked();
+            Object monitor = getTracker() == null? null: getTracker().tracked();
             if ( monitor != null )
             {
                 synchronized ( monitor )
@@ -940,7 +957,7 @@ public class DependencyManager<S, T> imp
             m_componentManager.log( LogService.LOG_DEBUG, "dm {0} tracking {1} SingleStatic removed {2} (exit)", new Object[] {getName(), trackingCount, serviceReference}, null );
         }
 
-        public boolean open()
+        public boolean prebind()
         {
             boolean success = m_dependencyMetadata.isOptional();
             if ( success || !getTracker().isEmpty() )
@@ -987,7 +1004,7 @@ public class DependencyManager<S, T> imp
 
         public Collection<RefPair<T>> getRefs( AtomicInteger trackingCount )
         {
-            Object monitor = getTracker().tracked();
+            Object monitor = getTracker() == null? null: getTracker().tracked();
             if ( monitor != null )
             {
                 synchronized ( monitor )
@@ -1006,7 +1023,7 @@ public class DependencyManager<S, T> imp
     private class NoPermissionsCustomizer implements Customizer<T>
     {
 
-        public boolean open()
+        public boolean prebind()
         {
             return false;
         }
@@ -1386,7 +1403,7 @@ public class DependencyManager<S, T> imp
 
     boolean prebind()
     {
-        return customizer.open();
+        return customizer.prebind();
     }
 
     /**
@@ -1423,10 +1440,12 @@ public class DependencyManager<S, T> imp
         boolean success = m_dependencyMetadata.isOptional();
         AtomicInteger trackingCount =  new AtomicInteger( );
         Collection<RefPair<T>> refs;
+        CountDownLatch openLatch = new CountDownLatch(1);
         synchronized ( trackerRef.get().tracked() )
         {
             refs = customizer.getRefs( trackingCount );
             edgeInfo.setOpen( trackingCount.get() );
+            edgeInfo.setOpenLatch( openLatch );
         }
         m_componentManager.log( LogService.LOG_DEBUG,
             "For dependency {0}, optional: {1}; to bind: {2}",
@@ -1445,6 +1464,7 @@ public class DependencyManager<S, T> imp
                 success = true;
             }
         }
+        openLatch.countDown();
         return success;
     }
 
@@ -1466,7 +1486,8 @@ public class DependencyManager<S, T> imp
         {
             refPairs = customizer.getRefs( trackingCount );
             edgeInfo.setClose( trackingCount.get() );
-            edgeInfo.setLatch( latch );
+            edgeInfo.setCloseLatch( latch );
+        }
 
         m_componentManager.log( LogService.LOG_DEBUG,
                 "DependencyManager: {0} close component unbinding from {1} at tracking count {2} refpairs: {3}",
@@ -1480,7 +1501,6 @@ public class DependencyManager<S, T> imp
             }
 
         }
-        }
         latch.countDown();
     }
 
@@ -1614,6 +1634,19 @@ public class DependencyManager<S, T> imp
                     return;
                 }
             }
+            try
+            {
+                if (!info.getOpenLatch().await( getLockTimeout(), TimeUnit.MILLISECONDS ))
+                {
+                    m_componentManager.log( LogService.LOG_WARNING,
+                            "DependencyManager : invokeUpdatedMethod : timeout on open latch {0}",  new Object[] {getName()}, null );
+                    m_componentManager.dumpThreads();
+                }
+            }
+            catch ( InterruptedException e )
+            {
+                Thread.currentThread().interrupt();
+            }
             if ( !getServiceObject( m_bindMethods.getUpdated(), refPair ))
             {
                 m_componentManager.log( LogService.LOG_WARNING,
@@ -1660,26 +1693,45 @@ public class DependencyManager<S, T> imp
             if (info.outOfRange( trackingCount ) )
             {
                 //wait for unbinds to complete
-                if (info.getLatch() != null)
+                if (info.getCloseLatch() != null)
                 {
                     try
                     {
-                        info.getLatch().await(  );
+                        if (!info.getCloseLatch().await( getLockTimeout(), TimeUnit.MILLISECONDS ) )
+                        {
+                            m_componentManager.log( LogService.LOG_WARNING,
+                                    "DependencyManager : invokeUnbindMethod : timeout on close latch {0}",  new Object[] {getName()}, null );
+                            m_componentManager.dumpThreads();
+                        }
                     }
                     catch ( InterruptedException e )
                     {
+                        Thread.currentThread().interrupt();
                         //ignore
                     }
                 }
                 //ignore events after close started or we will have duplicate unbinds.
                 return;
             }
+            try
+            {
+                if (!info.getOpenLatch().await( getLockTimeout(), TimeUnit.MILLISECONDS ))
+                {
+                    m_componentManager.log( LogService.LOG_WARNING,
+                            "DependencyManager : invokeUnbindMethod : timeout on open latch {0}",  new Object[] {getName()}, null );
+                    m_componentManager.dumpThreads();
+                }
+            }
+            catch ( InterruptedException e )
+            {
+                // TODO Auto-generated catch block
+            }
 
             if (refPair == null)
             {
                 //TODO should this be possible? If so, reduce or eliminate logging
                 m_componentManager.log( LogService.LOG_WARNING,
-                        "DependencyManager : invokeUnbindMethod : Component set, but reference not present", null );
+                        "DependencyManager : invokeUnbindMethod : Component set, but reference not present {0}",  new Object[] {getName()}, null );
                 return;
             }
             if ( !getServiceObject( m_bindMethods.getUnbind(), refPair ))
@@ -1705,6 +1757,11 @@ public class DependencyManager<S, T> imp
                 "DependencyManager : Component not set, no need to call unbind method", null );
         }
     }
+    
+    private long getLockTimeout()
+    {
+        return m_componentManager.getLockTimeout();
+    }
 
 
     //------------- Service target filter support -----------------------------

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/EdgeInfo.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/EdgeInfo.java?rev=1470394&r1=1470393&r2=1470394&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/EdgeInfo.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/EdgeInfo.java Mon Apr 22 06:44:24 2013
@@ -24,21 +24,31 @@ class EdgeInfo
 {
     private int open = -1;
     private int close = -1;
-    private CountDownLatch latch;
+    private CountDownLatch openLatch;
+    private CountDownLatch closeLatch;
 
     public void setClose( int close )
     {
         this.close = close;
     }
 
-    public CountDownLatch getLatch()
+    public CountDownLatch getOpenLatch()
     {
-        return latch;
+        return openLatch;
     }
 
-    public void setLatch( CountDownLatch latch )
+    public void setOpenLatch( CountDownLatch latch )
     {
-        this.latch = latch;
+        this.openLatch = latch;
+    }
+    public CountDownLatch getCloseLatch()
+    {
+        return closeLatch;
+    }
+
+    public void setCloseLatch( CountDownLatch latch )
+    {
+        this.closeLatch = latch;
     }
 
     public void setOpen( int open )

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/RegistrationManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/RegistrationManager.java?rev=1470394&r1=1470393&r2=1470394&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/RegistrationManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/RegistrationManager.java Mon Apr 22 06:44:24 2013
@@ -173,10 +173,12 @@ abstract class RegistrationManager<T>
                     {
                         log( LogService.LOG_ERROR, "Timeout waiting for reg change to complete {0}", new Object[]
                                 {rsw.getRegState()}, null);
+                        reportTimeout();
                     }
                 }
                 catch ( InterruptedException e )
                 {
+                    Thread.currentThread().interrupt();
                     log( LogService.LOG_ERROR, "Interrupted exception waiting for reg change to complete {0}", new Object[]
                             {rsw.getRegState()}, null);
                 }
@@ -193,6 +195,8 @@ abstract class RegistrationManager<T>
     
     abstract long getTimeout();
     
+    abstract void reportTimeout();
+    
     T getServiceRegistration()
     {
         return m_serviceRegistration;

Modified: felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/RegistrationManagerTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/RegistrationManagerTest.java?rev=1470394&r1=1470393&r2=1470394&view=diff
==============================================================================
--- felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/RegistrationManagerTest.java (original)
+++ felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/RegistrationManagerTest.java Mon Apr 22 06:44:24 2013
@@ -133,6 +133,13 @@ public class RegistrationManagerTest
             // TODO Auto-generated method stub
             return 10;
         }
+
+        @Override
+        void reportTimeout()
+        {
+            // TODO Auto-generated method stub
+            
+        }
         
     }
 }