Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 330874 - ConcurrentModificationException on faceted project creation
Summary: ConcurrentModificationException on faceted project creation
Status: RESOLVED FIXED
Alias: None
Product: WTP Common Tools
Classification: WebTools
Component: wst.common (show other bugs)
Version: 3.1   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: 3.2.3   Edit
Assignee: Chuck Bridgham CLA
QA Contact: Carl Anderson CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 351599
  Show dependency tree
 
Reported: 2010-11-22 23:32 EST by Kevin Tapperson CLA
Modified: 2011-07-08 13:04 EDT (History)
0 users

See Also:
ccc: review+


Attachments
stack traces of the offending threads as caught in the debugger (7.77 KB, text/plain)
2010-11-22 23:40 EST, Kevin Tapperson CLA
no flags Details
possible patch (10.44 KB, patch)
2010-11-30 16:53 EST, Chuck Bridgham CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Kevin Tapperson CLA 2010-11-22 23:32:50 EST
Build Identifier: M20100211-1343

We have a custom project facet that we add on top of the wst web facet.  Our facet adds a considerable number of files to the project.  During the completion of our facet installation, the facet framework calls broadcastPostChange() which proceeds to process all of the resources added to the project.  We usually encounter a ConcurrentModificationException during this processing as another worker/job thread attempts to modify the ProjectResourceSetImpl$SynchronizedResourcesEList collection at the same time.  I am attaching a pair of stack traces from the debugger showing the offending threads.

Reproducible: Sometimes

Steps to Reproduce:
1. Create a new project facet that adds a considerable number of files to the project.
2. Write a wizard that creates a new project and adds the wst web facet and then this new facet to the new project.
3. Wait for the ConcurrentModificationException - we encounter this about 80-90% of the time.
Comment 1 Kevin Tapperson CLA 2010-11-22 23:40:40 EST
Created attachment 183627 [details]
stack traces of the offending threads as caught in the debugger

This attachment contains 2 stack traces from the offending threads involved in the ConcurrentModificationException.

The ModalContext thread is the thread where our new project wizard is running.  It has created a new project, added the wst web facet and our custom facet to the project.  The facet framework is currently in the process of performing the completion steps of adding the new facets to the project and is broadcasting the post change event.  The thread appears to be examining all of the new resources added to the project to see if they should be added to a ProjectResourceSetImpl$SynchronizedResourcesEList collection.  The thread appears to obtain this collection for each new resource then iterate through the collection.  This process can take a bit of time as the number of new files in the project is large (approx 500-600 files).

The Worker-1 thread appears to be running a job called LoadingDDJob and is also working with the same ProjectResourceSetImpl$SynchronizedResourcesEList collection.  If this thread makes a call to add an item to the collection while the first thread (ModalContext) is iterating over the collection, the ConcurrentModificationException is thrown.
Comment 2 Carl Anderson CLA 2010-11-30 10:27:18 EST
Assigning to Chuck for initial investigation.

Also, the facet in question must be jst.web, not wst.web - it is loading the JavaArtifactEditModel in Worker-1 (and would not attempt the loadingDD job for wst.web, since Static Web projects do not have a Deployment Descriptor.)
Comment 3 Chuck Bridgham CLA 2010-11-30 12:05:48 EST
looking to re-implement getResources() to always return a copy and would delegate any modifications to the internal List for notifications etc...
Comment 4 Chuck Bridgham CLA 2010-11-30 16:53:57 EST
Created attachment 184191 [details]
possible patch
Comment 5 Chuck Bridgham CLA 2010-12-01 10:06:11 EST
I made the method for getting a seperate copy of the resources public, so the synchronizer could use that.  For safety reasons - I also delegated any "write" operation back to the original collection - but in these cases - only read scenarios are using the call.
Comment 6 Chuck Bridgham CLA 2010-12-01 17:15:15 EST
I made a tweak to the patch to do the following in the synchronizer for safety if the resourceSet is not the type I'm expecting...

if (resourceSet instanceof ProjectResourceSetImpl) {
			ProjectResourceSetImpl projResSet = (ProjectResourceSetImpl)resourceSet;
			allResources = projResSet.getImmutableResources();
		} else {
			allResources = resourceSet.getResources();
		}
Comment 7 Carl Anderson CLA 2010-12-01 19:30:25 EST
Chuck, did you mean to attach an additional patch with the updated check?
Comment 8 Chuck Bridgham CLA 2010-12-02 10:18:19 EST
Yes - thanks...   this is checked in...