Bug 305863 - org.eclipse.core.internal.runtime.AdapterManager is not thread safe
Summary: org.eclipse.core.internal.runtime.AdapterManager is not thread safe
Status: RESOLVED FIXED
Alias: None
Product: Equinox
Classification: Eclipse Project
Component: Components (show other bugs)
Version: 3.6   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: 3.6 M7   Edit
Assignee: equinox.components-inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords: greatbug
Depends on:
Blocks:
 
Reported: 2010-03-15 11:07 EDT by Filip Hrbek CLA
Modified: 2010-03-15 13:42 EDT (History)
2 users (show)

See Also:


Attachments
Solution proposal (966 bytes, patch)
2010-03-15 11:10 EDT, Filip Hrbek CLA
john.arthorne: iplog+
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Filip Hrbek CLA 2010-03-15 11:07:04 EDT
I had difficulties with parallel loading of p2 repositories (in most cases I got "Transfer initialization error" on loading of several repositories).

After deep debugging I concluded that the problem stems from the AdapterManager, method getFactories():

public HashMap getFactories() {
    // avoid the synchronize if we don't have to call it
    if (lazyFactoryProviders.size() == 0)
        return factories;
    synchronized (lazyFactoryProviders) {
        while (lazyFactoryProviders.size() > 0) {
            IAdapterManagerProvider provider =
                (IAdapterManagerProvider) lazyFactoryProviders.remove(0);
            if (provider.addFactories(this))
                flushLookup();
        }
    }
    return factories;
}

Consider two threads competing on getting the factory map:

1. Thread (1) checks the size of lazyFactoryProviders, it is grater than zero
2. Thread (1) enters the synchronized block
3. Thread (1) checks the size again, it is still grater than zero
4. Thread (1) picks&removes the first factory provider from the collection
5. Thread (2) checks the size of lazyFactoryProviders, it is now equal to zero!
6. Thread (2) returns the factories (where the desired factory is still missing)
7. Thread (2) searches for the desired factory in returned map
8. Thread (2) fails on the factory not being found!!!
9. Thread (1) adds the factory created by the picked provider to factories
10. Thread (1) returns the properly initialized map of factories
11. Thread (1) continues successfully since the desired factory is present

Solution: Remove the first lines and let the whole operation be always synchronized. Checking the size of the collection is not a performance issue.
Comment 1 Filip Hrbek CLA 2010-03-15 11:10:11 EDT
Created attachment 162050 [details]
Solution proposal

Apply this patch to solve the problem.
Comment 2 Thomas Watson CLA 2010-03-15 11:35:30 EDT
I agree and the patch looks good.  John, do you agree?
Comment 3 John Arthorne CLA 2010-03-15 13:37:08 EDT
Yes, I agree the patch looks good. I have run all the tests and committed this fix to HEAD. Great find!