Community
Participate
Working Groups
Using Eclipse 3.4 M6. While stopping the org.eclipse.equinox.log bundle it is possible for a deadlock to happen due to too much synchronization in the bundle Activator's stop(BundleContext) method. When a bundle unregisters a service the OSGi framework dispatches events, so holding a lock at this time can cause a deadlock. Today, the stop(BundleContext) method signature includes the synchronized keyword, making the entire method synchronized. The scope of the synchronization should not include the unregistration of the various services. I shall attach a patch to the bundle's Activator that: 1. Replaces the synchronized keyword in the method signature with a block of synchronized code. 2. Moves the unregistration of the various services to the top of the method and placed them outside of the block of synchronized code. -- Steps to Reproduce -- 0. Unzip the attached example project zip directly into an Eclipse workspace and import the project using File > Import... > Existing Project into Workspace. 1. Place a breakpoint on line 37 of the Counter example class. 2. Place a breakpoint on line 45 of the ServiceComponent example class. 3. In the com.sample.counter project, debug using the file /launch/Counter.launch file. 4. Upon execution the "Counter" thread will hit the breakpoint in step 1. 5. At the Equinox console type ss. The bundles should be as follows: 0 ACTIVE org.eclipse.osgi_3.4.0.v20080326 1 ACTIVE org.eclipse.equinox.util_1.0.0.v20080303 2 ACTIVE org.eclipse.equinox.log_1.1.0.v20080303 3 ACTIVE com.sample.counter_1.0.0 4 ACTIVE org.eclipse.osgi.services_3.1.200.v20071203 5 ACTIVE org.eclipse.equinox.ds_1.0.0.v20080310 6. Use the console's stop command to stop the org.eclipse.equinox.log bundle. 7. The "OSGi Console" thread will hit the breakpoint in step 2. Do not touch this thread yet. 8. Back on the "Counter" thread, step into the log(int, String) method: logService.log(LogService.LOG_INFO, message); 9. Continue stepping over the next couple of lines until you are on the line: tempLog.log(level, message, bundle, null, null); 10. Step into this line. You'll now be in the org.eclipse.equinox.log bundle's Activator. 11. Keep stepping over lines until you are inside the synchronized block. Due to a previously held lock you will not be able to step in to the synchronized block, but try. 12. Go back to the "OSGi Console" thread and step into the line: counter.unbind(logService); 13. Keep stepping over until you are inside the synchronized. Due to a previously held lock you will not be able to step in to the synchronized block, but try. 14. You are now deadlocked. The "OSGi Console" thread hold the Acviator's lock first, then it tries to hold the Counter's lock. The "Counter" thread holds the Counter's lock first, then it tries to hold the Activator's lock. 15. You can confirm the deadlock by suspending the "OSGi Console" thread and the "Counter" thread. Also, the console is unresponsive. The cause of the problem is that the org.eclipse.equinox.log bundle's Activator is holding a lock on "this" while unregistering its services, which prevents the Counter class' thread from cleanly finishing up. The Counter class has appropriate synchronization to ensure that the LogService is not pulled out from under it. The LogService is an optional service and is bound dynamically to the Counter using a DS service component. This is just background information that is not part of the bug itself. This is not a DS problem.
Created attachment 94984 [details] An example project that demonstrates the problem.
Created attachment 94985 [details] Patch to org.eclipse.equinox.log.Activator
Look at for M7.
Patch looks good. As always thanks for the great bug description Simon. Marking as greatbug and contributed.
Thank you Tom, it's my pleasure.