# HG changeset patch # User Ed Swartz # Date 1285026657 18000 # Node ID 38adc1f9b9ce7b94254bd03245b3e67cfe2192e2 # Parent 1d3b78a2f5784c8dda6ed6e8fbb3427893d8ab11 Fix bug 11274. Don't hold a lock on projectInfoMap for so long, fetching interesting mmp/bld.inf/etc list outside the lock instead. Add a temporary resource listener just in case resources are modified when we're not looking (I never saw this fire). diff -r 1d3b78a2f578 -r 38adc1f9b9ce builder/com.nokia.carbide.cdt.builder/src/com/nokia/carbide/cdt/internal/builder/CarbideBuildManager.java --- a/builder/com.nokia.carbide.cdt.builder/src/com/nokia/carbide/cdt/internal/builder/CarbideBuildManager.java Sat Sep 18 16:37:44 2010 -0700 +++ b/builder/com.nokia.carbide.cdt.builder/src/com/nokia/carbide/cdt/internal/builder/CarbideBuildManager.java Mon Sep 20 18:50:57 2010 -0500 @@ -33,6 +33,7 @@ import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.WorkspaceJob; import org.eclipse.core.runtime.CoreException; @@ -194,7 +195,66 @@ // assert(oldInfo != null); projectInfoMap.put(project, newInfo); + } + + + // Update resources-to-listen-to outside the lock (bug 11274). + // + // This invokes listenForReferencedFileChanges() to figure out what + // files to listen to (mmp/bld.inf/mmh/c/c++) that may affect the + // indexer state. + // + // By doing this outside a lock and after the project has changed, + // it is *possible* that some other listener could sneak in and + // modify a referenced file before we know we need to listen to it. + + // So listen to all changes in the meantime. + final Set resourcesModifiedDuringSetup = new HashSet(); + + IResourceChangeListener modifiedFilesListener = new IResourceChangeListener() { + + public void resourceChanged(IResourceChangeEvent event) { + // look for all modifying changes + if (event.getDelta() == null + || event.getDelta().getKind() != IResourceDelta.CHANGED + || event.getType() != IResourceChangeEvent.POST_CHANGE) + return; + + IResourceDelta delta = event.getDelta(); + if (delta.getKind() == IResourceDelta.ADDED || delta.getKind() == IResourceDelta.REMOVED || + (delta.getKind() == IResourceDelta.CHANGED && (delta.getFlags() & IResourceDelta.CONTENT) != 0)) { + resourcesModifiedDuringSetup.add(event.getResource().getFullPath()); + } + } + }; + ResourcesPlugin.getWorkspace().addResourceChangeListener(modifiedFilesListener); + + try { addProjectListener(newInfo); + } finally { + + // Now, see if the modified files are related to the newly detected files + ResourcesPlugin.getWorkspace().removeResourceChangeListener(modifiedFilesListener); + + if (!resourcesModifiedDuringSetup.isEmpty()) { + System.out.println("Changes detected during project listener update:"); + for (IPath path : resourcesModifiedDuringSetup) { + System.out.println("\t" + path); + } + + WorkspaceJob job = new WorkspaceJob("Updating for files changed during refresh") { + + @Override + public IStatus runInWorkspace(IProgressMonitor monitor) + throws CoreException { + resourceChangedListener.fireListenersOnPaths(resourcesModifiedDuringSetup); + return Status.OK_STATUS; + } + }; + job.setRule(ResourcesPlugin.getWorkspace().getRoot()); + job.schedule(); + } + } } diff -r 1d3b78a2f578 -r 38adc1f9b9ce core/com.nokia.cpp.utils.core/src/com/nokia/cpp/internal/api/utils/core/MultiResourceChangeListenerDispatcher.java --- a/core/com.nokia.cpp.utils.core/src/com/nokia/cpp/internal/api/utils/core/MultiResourceChangeListenerDispatcher.java Sat Sep 18 16:37:44 2010 -0700 +++ b/core/com.nokia.cpp.utils.core/src/com/nokia/cpp/internal/api/utils/core/MultiResourceChangeListenerDispatcher.java Mon Sep 20 18:50:57 2010 -0500 @@ -150,4 +150,17 @@ } } + /** + * Fire resource changed listeners on the workspace paths in the given list, + * if they are registered. + * @param pathList + */ + public void fireListenersOnPaths(Collection pathList) { + for (Pair entry : trackedResources) { + if (pathList.contains(entry.first)) { + entry.second.resourceChanged(entry.first); + } + } + } + }