Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-dev] Race condition in CProjectDescriptionManager.updateProjectDescriptions()?

I am having a problem with a race condition between the GCCBuiltinSpecsDetector and a job of my own plugin: I am trying to modify the project description by calling

  ICProjectDescription writableProject = CoreModel.getDefault().getProjectDescription(m_project);
  // .. modify writableProject ...
  CoreModel.getDefault().setProjectDescription(m_project, writableProject, false, monitor);

but find that my modifications are overwritten soon after by GCCBuiltinSpecsDetector writing back what appears to be an older project description.

This happens in org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager.updateProjectDescriptions(IProject[], IProgressMonitor), called indirectly from org.eclipse.cdt.managedbuilder.language.settings.providers.AbstractBuiltinSpecsDetector.execute() via AbstractBuiltinSpecsDetector.runForEachLanguage() ... LanguageSettingsSerializableProvider.serializeLanguageSettings() ... LanguageSettingsProvidersSerializer.notifyLanguageSettingsChangeListeners() ... CModelManager.handleEvent(ILanguageSettingsChangeEvent). 

CProjectDescriptionManager.updateProjectDescriptions() as per the logic in AbstractBuiltinSpecsDetector.execute() runs with the scheduling rule of the project and gets the project description (A), then schedules its second part to write it back (B) with the scheduling rule of the workspace root (because project does not contain workspace root). Between the execution of A and B, no scheduling rules are held and others are free to call getProjectDescription() and setProjectDescription() themselves, only to have their modifications overwritten by B.

Before I file a bugzilla I'd like to ask here: Is this a bug in CDT or is there anything I can do in my code to prevent this? I couldn't think of anything so far. It seems like a bug to me, updateProjectDescriptions() shouldn't let its two parts be separated like this, getProjectDescription() and setProjectDescription() should be executed as an atomic unit while holding the scheduling rule of at least the affected project (in fact, it must be at least the workspace root because that's what setProjectDescription() uses internally).

As an experiment I tried modifying AbstractBuiltinSpecsDetector.execute() to always run its job with the workspace root scheduling rule, so that updateProjectDescriptions() wouldn't schedule its part B but run it synchronously, however that just resulted in an infinite stream of GCCBuiltinSpecsDetector executions, because every call of setProjectDescription() causes another execution via XmlProjectDescriptionStorage.setCurrentDescription() ... LanguageSettingsProvidersSerializer.reRegisterListeners() ... AbstractBuiltinSpecsDetector.registerListener(). (Why is it doing that anyway? This has annoyed me in the past already. GCCBuiltinSpecsDetector seems to run unnecessarily every (?) time you make some small change to the project using get/setProjectDescription().)

I am not sure what a proper solution would be. Maybe updateProjectDescriptions() should put both the getting and the setting of project descriptions into its scheduled part (B)? I don't even completely understand yet what the purpose of updateProjectDescriptions() is - documentation says it recalculates "cached data", but I'm not familiar enough with CDT internals to know what "cached data" is.

Hope someone can shed some light on this.

 -Christian



Back to the top