Yes, open a bug Tim. I can see that a fix is needed here.
-- 

BJ Hargrave
Senior Technical Staff Member, IBM
OSGi Fellow and CTO of the OSGi Alliance
[email protected]

office: +1 386 848 1781
mobile: +1 386 848 3788




From:
Tim Diekmann <[email protected]>
To:
Equinox development mailing list <[email protected]>
Date:
2010/01/29 22:46
Subject:
[equinox-dev] problem with ServiceTracker.open() and refreshThread      in 
Equinox
Sent by:
[email protected]



I ran into a problem with Equinox 3.5.1.R35x_v20090806:

In my log file I find the following exception stack trace after calling 
PackageAdmin.refreshPackages(null).

org.osgi.framework.BundleException: Exception in 
com.tibco.xxx.Activator.start() of bundle com.tibco.xxx.
at 
org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:805)
at 
org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:754)
at 
org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:352)
at 
org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:280)
at 
org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:272)
at com.tibco.xxx.refreshRuntime(xxx.java:872)
at com.tibco.xx.access$6(xxxImpl.java:569)
at com.tibco.xxx$2.run(xxxImpl.java:229)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.IllegalStateException: The service has been 
unregistered
at 
org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.getReferenceImpl(ServiceRegistrationImpl.java:277)
at 
org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.lookupServiceRegistrations(ServiceRegistry.java:867)
at 
org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.getServiceReferences(ServiceRegistry.java:290)
at 
org.eclipse.osgi.framework.internal.core.BundleContextImpl.getAllServiceReferences(BundleContextImpl.java:577)
at 
org.osgi.util.tracker.ServiceTracker.getInitialReferences(ServiceTracker.java:360)
at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:321)
at com.tibco.xxx.start(xxx.java:150)
at com.tibco.xxx.Activator.start(Activator.java:39)
at 
org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:782)
at java.security.AccessController.doPrivileged(Native Method)
at 
org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:773)

The exception is thrown while starting a bundle after the refreshPackages 
call. I assume the refreshThread is still ongoing in the background and as 
part of the process stops and restarts bundles, which causes OSGi services 
to be unregistered and then (hopefully) registered again.

The ServiceTracker of the bundle that is started wants to look for all 
services that have a certain property set. However, during the initial 
scan of all services, one of them is unregistered, which causes the seen 
exception.

There seems to be a race condition in which lookupServiceRegistrations() 
acquires the lock to ServiceRegistry and copies the results to an 
ArrayList.

private List lookupServiceRegistrations(String clazz, Filter filter) {
List result;
synchronized (this) {
if (clazz == null) { /* all services */
result = allPublishedServices;
} else {
/* services registered under the class name */
result = (List) publishedServicesByClass.get(clazz);
}

if ((result == null) || (result.size() == 0)) {
return Collections.EMPTY_LIST;
}

result = new ArrayList(result); /* make a new list since we don't want to 
change the real list */
}

In the meantime the service is unregistered and removed from 
allPublishedServices:

void removeServiceRegistration(BundleContextImpl context, 
ServiceRegistrationImpl serviceReg) {
// Remove the ServiceRegistrationImpl from the list of Services published 
by BundleContextImpl.
List contextServices = (List) publishedServicesByContext.get(context);
if (contextServices != null) {
contextServices.remove(serviceReg);
}

// Remove the ServiceRegistrationImpl from the list of Services published 
by Class Name.
String[] clazzes = serviceReg.getClasses();
for (int i = 0, size = clazzes.length; i < size; i++) {
String clazz = clazzes[i];
List services = (List) publishedServicesByClass.get(clazz);
services.remove(serviceReg);
}

// Remove the ServiceRegistrationImpl from the list of all published 
Services.
allPublishedServices.remove(serviceReg);
}

However, lookupServiceRegistrations() goes on to iterate over the result 
list and runs into the exception above.

for (Iterator iter = result.iterator(); iter.hasNext();) {
ServiceRegistrationImpl registration = (ServiceRegistrationImpl) 
iter.next();
if (!filter.match(registration.getReferenceImpl())) {
iter.remove();
}
}


Has anyone seen this? Is this a know problem? I guess I could file a bug 
for this.

Thanks,

   Tim.

"It is a simple task to make things complex, but a complex task to make 
them simple."
 -- Fortune Cookie
_______________________________________________
equinox-dev mailing list
[email protected]
https://dev.eclipse.org/mailman/listinfo/equinox-dev

_______________________________________________
equinox-dev mailing list
[email protected]
https://dev.eclipse.org/mailman/listinfo/equinox-dev

Reply via email to