Deadlock in SCR ComponentRegistry updateChangeCount
@@ -32,6 +32,7 @@ import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicLong;
import org.apache.felix.scr.impl.inject.ComponentMethods;
import org.apache.felix.scr.impl.inject.internal.ComponentMethodsImpl;
@@ -701,18 +702,18 @@ public class ComponentRegistry
}
- private final Object changeCountLock = new Object();
+ private final AtomicLong changeCount = new AtomicLong();
- private volatile long changeCount;
+ private volatile Timer changeCountTimer;
- private volatile Timer timer;
+ private final Object changeCountTimerLock = new Object();
private volatile ServiceRegistration<ServiceComponentRuntime> registration;
public Dictionary<String, Object> getServiceRegistrationProperties()
{
final Dictionary<String, Object> props = new Hashtable<>();
- props.put(PROP_CHANGECOUNT, this.changeCount);
+ props.put(PROP_CHANGECOUNT, this.changeCount.get());
return props;
}
@@ -726,13 +727,14 @@ public class ComponentRegistry
{
if ( registration != null )
{
- synchronized ( changeCountLock )
- {
- this.changeCount++;
- final long count = this.changeCount;
- if ( this.timer == null )
- {
- this.timer = new Timer();
+ final long count = this.changeCount.incrementAndGet();
+
+ final Timer timer;
+ synchronized ( this.changeCountTimerLock ) {
+ if ( this.changeCountTimer == null ) {
+ this.changeCountTimer = new Timer();
+ }
+ timer = this.changeCountTimer;
}
try
{
@@ -740,10 +742,9 @@ public class ComponentRegistry
{
@Override
- public void run() {
- synchronized ( changeCountLock )
+ public void run()
{
- if ( changeCount == count )
+ if ( changeCount.get() == count )
{
try
{
@@ -753,10 +754,16 @@ public class ComponentRegistry
{
// we ignore this as this might happen on shutdown
}
- timer.cancel();
- timer = null;
+ synchronized ( changeCountTimerLock )
+ {
+ if ( changeCount.get() == count )
+ {
+ changeCountTimer.cancel();
+ changeCountTimer = null;
}
}
+
+ }
}
}, m_configuration.serviceChangecountTimeout());
}
@@ -768,4 +775,3 @@ public class ComponentRegistry
}
}
}
-}
