Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)?
Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)? [message #1518534] Sat, 20 December 2014 05:06 Go to next message
Nicolas Rouquette is currently offline Nicolas RouquetteFriend
Messages: 157
Registered: July 2009
Senior Member
Until recently, we haven't had to register dynamic metamodels in our Eclipse IDE for QVTO development. We could instead register metamodels via their implementations. As far as using the Eclipse IDE to compile source *.qvto files into executable *.qvtox files, the Eclipse QVTO compiler only cares that all metamodels involved have been properly registered. Using the implementations was the simplest way to go. This worked very well for us for several years until now...

Now, we have to deal with fundamentally different versions of metamodels (UML 2.4 and UML 2.5) both of which have dependencies on the same metamodels. The conventional approach would lead to nasty jar conflicts. To be fair, these different versions are not designed to coexist in the same JVM! Since for Eclipse QVTO development we don't technically need to "execute" the metamodel, I thought that I could instead register all of these metamodels as dynamic -- i.e., *.ecore, no java.

In principle it should work (It's been described in several places, including the EMF book). However, I've encountered some problems at Eclipse initialization.

I'm using Eclipse Luna with a lot of EMF-related technology (XCore, QVTO, DiffMerge, EASE, ....) Too much to extract a simple test case but I think the problem is fairly simple.

Basically, there are multiple Eclipse views that, at startup, query the EMF EPackage registry. In the stack traces below, there are 2 views involved:

- the Eclipse QVTO Metamodel Registry view (it shows all the registered metamodels)
- an Eclipse QVTO editor (which makes references to several registered metamodels)

Both initializations trigger NPEs.

Daemon Thread [org.eclipse.m2m.internal.qvt.oml.editor.ui.QvtReconciler] (Suspended (exception NullPointerException))	
	owns: XcoreResource  (id=113)	
	XcoreJavaProjectProvider.getJavaProject(ResourceSet) line: 97	
	XcoreJavaProjectProvider.getClassLoader(ResourceSet) line: 124	
	XcoreEcoreBuilder.getEPackage(XPackage) line: 195	
	XcoreModelAssociator.installDerivedState(DerivedStateAwareResource, boolean) line: 92	
	XcoreResource(DerivedStateAwareResource).installDerivedState(boolean) line: 159	
	XcoreResource(BatchLinkableResource).getContents() line: 133	
	RegistryReader$EPackageDescriptor$Dynamic.getEPackage() line: 251	
	EmfMetamodelDesc.getModel() line: 61	
	EmfMetamodelDesc.getLoadStatus() line: 91	
	MetamodelRegistry.toEPackageRegistry() line: 95	
	CompilerUtils.getEPackageRegistry(URI, IMetamodelRegistryProvider) line: 107	
	QVTOCompiler.getEPackageRegistry(URI) line: 529	
	QVTOCompiler.parse(UnitProxy, QvtCompilerOptions) line: 233	
	QVTOCompiler.doCompile(UnitProxy, QvtCompilerOptions, Monitor) line: 369	
	QVTOCompiler.compileSingleFile(UnitProxy, QvtCompilerOptions, Monitor) line: 326	
	QVTOCompiler.compile(UnitProxy[], QvtCompilerOptions, Monitor) line: 211	
	QVTOCompiler.compile(UnitProxy, QvtCompilerOptions, Monitor) line: 224	
	QvtCompilerFacade.compile(ITextEditor, IDocument, QvtCompilerOptions, IProgressMonitor) line: 77	
	QvtReconcilingStrategy.getCompilationResult(boolean) line: 90	
	QvtReconcilingStrategy.reconcileInternal() line: 74	
	QvtReconcilingStrategy.initialReconcile() line: 62	
	QvtReconciler(MonoReconciler).initialProcess() line: 105	
	AbstractReconciler$BackgroundThread.run() line: 173	


The Eclipse QVTO Metamodel Registry view:

Thread [main] (Suspended (exception NullPointerException))	
	owns: XcoreResource  (id=106)	
	XcoreJavaProjectProvider.getJavaProject(ResourceSet) line: 97	
	XcoreJavaProjectProvider.getClassLoader(ResourceSet) line: 124	
	XcoreEcoreBuilder.getEPackage(XPackage) line: 195	
	XcoreModelAssociator.installDerivedState(DerivedStateAwareResource, boolean) line: 92	
	XcoreResource(DerivedStateAwareResource).installDerivedState(boolean) line: 159	
	XcoreResource(BatchLinkableResource).getContents() line: 133	
	RegistryReader$EPackageDescriptor$Dynamic.getEPackage() line: 251	
	EmfMetamodelDesc.getModel() line: 61	
	MetamodelBrowserView$3(MetamodelBrowser).doCreateInput() line: 502	
	MetamodelBrowser$5.run() line: 473	
	BusyIndicator.showWhile(Display, Runnable) line: 70	
	MetamodelBrowserView$3(MetamodelBrowser).createInput() line: 471	
	MetamodelBrowserView$3(MetamodelBrowser).<init>(Composite, int) line: 168	
	MetamodelBrowserView$3(MetamodelBrowser).<init>(Composite) line: 145	
	MetamodelBrowserView$3.<init>(MetamodelBrowserView, Composite) line: 108	
	MetamodelBrowserView.createPartControl(Composite) line: 108	
	CompatibilityView(CompatibilityPart).createPartControl(IWorkbenchPart, Composite) line: 141	
	CompatibilityView.createPartControl(IWorkbenchPart, Composite) line: 155	
	CompatibilityView(CompatibilityPart).create() line: 327	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43	
	Method.invoke(Object, Object...) line: 483	
	MethodRequestor.execute() line: 55	
	InjectorImpl.processAnnotated(Class<Annotation>, Object, Class<?>, PrimaryObjectSupplier, PrimaryObjectSupplier, ArrayList<Class<?>>) line: 888	
	InjectorImpl.processAnnotated(Class<Annotation>, Object, Class<?>, PrimaryObjectSupplier, PrimaryObjectSupplier, ArrayList<Class<?>>) line: 869	
	InjectorImpl.inject(Object, PrimaryObjectSupplier, PrimaryObjectSupplier) line: 120	
	InjectorImpl.internalMake(Class<?>, PrimaryObjectSupplier, PrimaryObjectSupplier) line: 337	
	InjectorImpl.make(Class<T>, PrimaryObjectSupplier) line: 258	
	ContextInjectionFactory.make(Class<T>, IEclipseContext) line: 162	
	ReflectionContributionFactory.createFromBundle(Bundle, IEclipseContext, IEclipseContext, URI) line: 104	
	ReflectionContributionFactory.doCreate(String, IEclipseContext, IEclipseContext) line: 73	
	ReflectionContributionFactory.create(String, IEclipseContext) line: 55	
	ContributedPartRenderer.createWidget(MUIElement, Object) line: 127	
	PartRenderingEngine.createWidget(MUIElement, Object) line: 983	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 662	
	PartRenderingEngine$6.run() line: 547	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement, Object, IEclipseContext) line: 531	
	ElementReferenceRenderer.createWidget(MUIElement, Object) line: 69	
	PartRenderingEngine.createWidget(MUIElement, Object) line: 983	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 662	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	StackRenderer.showTab(MUIElement) line: 1250	
	StackRenderer(LazyStackRenderer).postProcess(MUIElement) line: 100	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 678	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68	
	SashRenderer.processContents(MElementContainer<MUIElement>) line: 185	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 674	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68	
	SashRenderer.processContents(MElementContainer<MUIElement>) line: 185	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 674	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68	
	SashRenderer.processContents(MElementContainer<MUIElement>) line: 185	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 674	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	PerspectiveRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68	
	PerspectiveRenderer.processContents(MElementContainer<MUIElement>) line: 49	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 674	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	PerspectiveStackRenderer.showTab(MUIElement) line: 103	
	PerspectiveStackRenderer(LazyStackRenderer).postProcess(MUIElement) line: 100	
	PerspectiveStackRenderer.postProcess(MUIElement) line: 77	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 678	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68	
	SashRenderer.processContents(MElementContainer<MUIElement>) line: 185	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 674	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	WBWRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68	
	WBWRenderer.processContents(MElementContainer<MUIElement>) line: 664	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 674	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	PartRenderingEngine$9.run() line: 1078	
	Realm.runWithDefault(Realm, Runnable) line: 332	
	PartRenderingEngine.run(MApplicationElement, IEclipseContext) line: 1032	
	E4Workbench.createAndRunUI(MApplicationElement) line: 148	
	Workbench$5.run() line: 636	
	Realm.runWithDefault(Realm, Runnable) line: 332	
	Workbench.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 579	
	PlatformUI.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 150	
	IDEApplication.start(IApplicationContext) line: 135	
	EclipseAppHandle.run(Object) line: 196	
	EclipseAppLauncher.runApplication(Object) line: 134	
	EclipseAppLauncher.start(Object) line: 104	
	EclipseStarter.run(Object) line: 380	
	EclipseStarter.run(String[], Runnable) line: 235	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43	
	Method.invoke(Object, Object...) line: 483	
	Main.invokeFramework(String[], URL[]) line: 648	
	Main.basicRun(String[]) line: 603	
	Main.run(String[]) line: 1465	
	Main.main(String[]) line: 1438	


These 2 threads are trying to register the same EPackage: xcore.lang

The NPE is caused by the fact that the ResourceSet's resources contains a NULL!

      for (Resource resource : resourceSet.getResources())
      {
        URI uri = resource.getURI(); // NPE because resource is null!
        ...
      }


There was a misleading NPE that turns out to be a minor vulnerability in the EMF RegistryReader:

diff --git a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/plugin/RegistryReader.java b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/plugin/RegistryReader.java
index 9666a50..bf098c3 100644
--- a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/plugin/RegistryReader.java
+++ b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/plugin/RegistryReader.java
@@ -24,9 +24,11 @@ import org.eclipse.core.runtime.IExtensionRegistry;
 import org.eclipse.core.runtime.IRegistryChangeEvent;
 import org.eclipse.core.runtime.IRegistryChangeListener;
 import org.eclipse.emf.common.CommonPlugin;
+import org.eclipse.emf.common.util.EList;
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.common.util.WrappedException;
 import org.eclipse.emf.ecore.EFactory;
+import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EPackage;
 import org.eclipse.emf.ecore.EcorePackage;
 import org.eclipse.emf.ecore.resource.Resource;
@@ -244,7 +246,11 @@ public abstract class RegistryReader
             }
             else
             {
-              return (EPackage) EcoreUtil.getObjectByType(resourceSet.getResource(locationURI, true).getContents(), EcorePackage.Literals.EPACKAGE);
+              Resource r = resourceSet.getResource(locationURI, true);
+              if (r != null)
+                       return (EPackage) EcoreUtil.getObjectByType(r.getContents(), EcorePackage.Literals.EPACKAGE);
+              else
+                   throw new RuntimeException("No EPackage found at: " + locationURI);
             }
           }
           else


Basically, the original code assumes that resourceSet.getResource(...) never returns null. AFAIK, there is no such guarantee at the point in the logic.

With this NPE vulnerability aside, we are left with the problem: how could a ResourceSet have a null resource?

This should not happen but it obviously does in this case.

The problem is really due to concurrent calls to ResourceSet.add(Resource) because
the default implementation (i.e. ResourceSetImpl) is not thread-safe for concurrent modification.

I managed to work around the problem by synchronizing calls to ResourceSetImpl::add(Resource):

diff --git a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/resource/impl/ResourceSetImpl.java b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/resource/impl/ResourceSetImpl.java
index 6f896e8..9792542 100644
--- a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/resource/impl/ResourceSetImpl.java
+++ b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/resource/impl/ResourceSetImpl.java
@@ -432,7 +432,9 @@ public class ResourceSetImpl extends NotifierImpl implements ResourceSet
     if (resourceFactory != null)
     {
       Resource result = resourceFactory.createResource(uri);
-      getResources().add(result);
+      if (result != null) {
+               getResources().add(result);
+      }
       return result;
     }
     else
@@ -609,6 +611,14 @@ public class ResourceSetImpl extends NotifierImpl implements ResourceSet
     {
       return size <= 4 ? super.contains(object) : object instanceof Resource && ((Resource)object).getResourceSet() == ResourceSetImpl.this;
     }
+
+       @Override
+       public boolean add(E object) {
+               synchronized(this) {
+                       return super.add(object);
+               }
+       }
+    
   }


The evidence that this workaround is effective is that if I comment out the synchronized guard in the call to super.add(object), then I get NPEs on 2 threads at initialization.

Has anyone encountered this problem before?

Is there a test case that involves plugins that register dynamic metamodels?

If yes, I'd like to see if I can reproduce this problem in a simpler environment by opening the Eclipse QVTO metamodel registry view and an Eclipse QVTO editor.
This seems to be enough to concurrent threads that will initialize the EMF EPackage registry and therefore force adding metamodel resources to the same ResourceSet.

On the other hand, it is rather interesting that these NPEs have systematically happened during the initialization of XCore even though the examples I made do not involve XCore's metamodels (except for the Eclipse QVTO Metamodel Registry view which shows all registered metamodels -- static & dynamic)

- Nicolas.
Re: Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)? [message #1518882 is a reply to message #1518534] Sat, 20 December 2014 09:52 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33113
Registered: July 2009
Senior Member
Nicolas,

Comments below.

On 20/12/2014 6:06 AM, Nicolas Rouquette wrote:
> Until recently, we haven't had to register dynamic metamodels in our
> Eclipse IDE for QVTO development. We could instead register metamodels
> via their implementations. As far as using the Eclipse IDE to compile
> source *.qvto files into executable *.qvtox files, the Eclipse QVTO
> compiler only cares that all metamodels involved have been properly
> registered. Using the implementations was the simplest way to go. This
> worked very well for us for several years until now...
>
> Now, we have to deal with fundamentally different versions of
> metamodels (UML 2.4 and UML 2.5) both of which have dependencies on
> the same metamodels. The conventional approach would lead to nasty jar
> conflicts. To be fair, these different versions are not designed to
> coexist in the same JVM! Since for Eclipse QVTO development we don't
> technically need to "execute" the metamodel, I thought that I could
> instead register all of these metamodels as dynamic -- i.e., *.ecore,
> no java.
>
> In principle it should work (It's been described in several places,
> including the EMF book). However, I've encountered some problems at
> Eclipse initialization.
>
> I'm using Eclipse Luna with a lot of EMF-related technology (XCore,
> QVTO, DiffMerge, EASE, ....) Too much to extract a simple test case
> but I think the problem is fairly simple.
>
> Basically, there are multiple Eclipse views that, at startup, query
> the EMF EPackage registry. In the stack traces below, there are 2
> views involved:
>
> - the Eclipse QVTO Metamodel Registry view (it shows all the
> registered metamodels)
> - an Eclipse QVTO editor (which makes references to several registered
> metamodels)
>
> Both initializations trigger NPEs.
>
>
> Daemon Thread
> [org.eclipse.m2m.internal.qvt.oml.editor.ui.QvtReconciler] (Suspended
> (exception NullPointerException))
> owns: XcoreResource (id=113)
> XcoreJavaProjectProvider.getJavaProject(ResourceSet) line: 97
> XcoreJavaProjectProvider.getClassLoader(ResourceSet) line: 124
> XcoreEcoreBuilder.getEPackage(XPackage) line: 195
> XcoreModelAssociator.installDerivedState(DerivedStateAwareResource, boolean)
> line: 92
> XcoreResource(DerivedStateAwareResource).installDerivedState(boolean)
> line: 159
> XcoreResource(BatchLinkableResource).getContents() line: 133
> RegistryReader$EPackageDescriptor$Dynamic.getEPackage() line: 251
> EmfMetamodelDesc.getModel() line: 61
> EmfMetamodelDesc.getLoadStatus() line: 91
> MetamodelRegistry.toEPackageRegistry() line: 95
> CompilerUtils.getEPackageRegistry(URI, IMetamodelRegistryProvider)
> line: 107
> QVTOCompiler.getEPackageRegistry(URI) line: 529
> QVTOCompiler.parse(UnitProxy, QvtCompilerOptions) line: 233
> QVTOCompiler.doCompile(UnitProxy, QvtCompilerOptions, Monitor)
> line: 369
> QVTOCompiler.compileSingleFile(UnitProxy, QvtCompilerOptions,
> Monitor) line: 326
> QVTOCompiler.compile(UnitProxy[], QvtCompilerOptions, Monitor)
> line: 211
> QVTOCompiler.compile(UnitProxy, QvtCompilerOptions, Monitor) line:
> 224
> QvtCompilerFacade.compile(ITextEditor, IDocument,
> QvtCompilerOptions, IProgressMonitor) line: 77
> QvtReconcilingStrategy.getCompilationResult(boolean) line: 90
> QvtReconcilingStrategy.reconcileInternal() line: 74
> QvtReconcilingStrategy.initialReconcile() line: 62
> QvtReconciler(MonoReconciler).initialProcess() line: 105
> AbstractReconciler$BackgroundThread.run() line: 173
>
>
> The Eclipse QVTO Metamodel Registry view:
>
>
> Thread [main] (Suspended (exception NullPointerException))
> owns: XcoreResource (id=106)
> XcoreJavaProjectProvider.getJavaProject(ResourceSet) line: 97
> XcoreJavaProjectProvider.getClassLoader(ResourceSet) line: 124
> XcoreEcoreBuilder.getEPackage(XPackage) line: 195
> XcoreModelAssociator.installDerivedState(DerivedStateAwareResource, boolean)
> line: 92
> XcoreResource(DerivedStateAwareResource).installDerivedState(boolean)
> line: 159
> XcoreResource(BatchLinkableResource).getContents() line: 133
> RegistryReader$EPackageDescriptor$Dynamic.getEPackage() line: 251
> EmfMetamodelDesc.getModel() line: 61
> MetamodelBrowserView$3(MetamodelBrowser).doCreateInput() line: 502
> MetamodelBrowser$5.run() line: 473
> BusyIndicator.showWhile(Display, Runnable) line: 70
> MetamodelBrowserView$3(MetamodelBrowser).createInput() line: 471
> MetamodelBrowserView$3(MetamodelBrowser).<init>(Composite, int)
> line: 168
> MetamodelBrowserView$3(MetamodelBrowser).<init>(Composite) line: 145
> MetamodelBrowserView$3.<init>(MetamodelBrowserView, Composite)
> line: 108
> MetamodelBrowserView.createPartControl(Composite) line: 108
> CompatibilityView(CompatibilityPart).createPartControl(IWorkbenchPart,
> Composite) line: 141
> CompatibilityView.createPartControl(IWorkbenchPart, Composite)
> line: 155
> CompatibilityView(CompatibilityPart).create() line: 327
> NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line:
> not available [native method]
> NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62
> DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
> Method.invoke(Object, Object...) line: 483
> MethodRequestor.execute() line: 55
> InjectorImpl.processAnnotated(Class<Annotation>, Object, Class<?>,
> PrimaryObjectSupplier, PrimaryObjectSupplier, ArrayList<Class<?>>)
> line: 888
> InjectorImpl.processAnnotated(Class<Annotation>, Object, Class<?>,
> PrimaryObjectSupplier, PrimaryObjectSupplier, ArrayList<Class<?>>)
> line: 869
> InjectorImpl.inject(Object, PrimaryObjectSupplier,
> PrimaryObjectSupplier) line: 120
> InjectorImpl.internalMake(Class<?>, PrimaryObjectSupplier,
> PrimaryObjectSupplier) line: 337
> InjectorImpl.make(Class<T>, PrimaryObjectSupplier) line: 258
> ContextInjectionFactory.make(Class<T>, IEclipseContext) line: 162
> ReflectionContributionFactory.createFromBundle(Bundle,
> IEclipseContext, IEclipseContext, URI) line: 104
> ReflectionContributionFactory.doCreate(String, IEclipseContext,
> IEclipseContext) line: 73
> ReflectionContributionFactory.create(String, IEclipseContext)
> line: 55
> ContributedPartRenderer.createWidget(MUIElement, Object) line: 127
> PartRenderingEngine.createWidget(MUIElement, Object) line: 983
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 662
> PartRenderingEngine$6.run() line: 547
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement, Object, IEclipseContext)
> line: 531
> ElementReferenceRenderer.createWidget(MUIElement, Object) line: 69
> PartRenderingEngine.createWidget(MUIElement, Object) line: 983
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 662
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> StackRenderer.showTab(MUIElement) line: 1250
> StackRenderer(LazyStackRenderer).postProcess(MUIElement) line: 100
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 678
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>)
> line: 68
> SashRenderer.processContents(MElementContainer<MUIElement>) line: 185
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>)
> line: 68
> SashRenderer.processContents(MElementContainer<MUIElement>) line: 185
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>)
> line: 68
> SashRenderer.processContents(MElementContainer<MUIElement>) line: 185
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> PerspectiveRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>)
> line: 68
> PerspectiveRenderer.processContents(MElementContainer<MUIElement>)
> line: 49
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> PerspectiveStackRenderer.showTab(MUIElement) line: 103
> PerspectiveStackRenderer(LazyStackRenderer).postProcess(MUIElement) line:
> 100
> PerspectiveStackRenderer.postProcess(MUIElement) line: 77
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 678
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>)
> line: 68
> SashRenderer.processContents(MElementContainer<MUIElement>) line: 185
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> WBWRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>)
> line: 68
> WBWRenderer.processContents(MElementContainer<MUIElement>) line: 664
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> PartRenderingEngine$9.run() line: 1078
> Realm.runWithDefault(Realm, Runnable) line: 332
> PartRenderingEngine.run(MApplicationElement, IEclipseContext)
> line: 1032
> E4Workbench.createAndRunUI(MApplicationElement) line: 148
> Workbench$5.run() line: 636
> Realm.runWithDefault(Realm, Runnable) line: 332
> Workbench.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 579
> PlatformUI.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 150
> IDEApplication.start(IApplicationContext) line: 135
> EclipseAppHandle.run(Object) line: 196
> EclipseAppLauncher.runApplication(Object) line: 134
> EclipseAppLauncher.start(Object) line: 104
> EclipseStarter.run(Object) line: 380
> EclipseStarter.run(String[], Runnable) line: 235
> NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line:
> not available [native method]
> NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62
> DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
> Method.invoke(Object, Object...) line: 483
> Main.invokeFramework(String[], URL[]) line: 648
> Main.basicRun(String[]) line: 603
> Main.run(String[]) line: 1465
> Main.main(String[]) line: 1438
>
>
> These 2 threads are trying to register the same EPackage: xcore.lang
>
> The NPE is caused by the fact that the ResourceSet's resources
> contains a NULL!
>
>
> for (Resource resource : resourceSet.getResources())
> {
> URI uri = resource.getURI(); // NPE because resource is null!
> ...
> }
>
>
> There was a misleading NPE that turns out to be a minor vulnerability
> in the EMF RegistryReader:
>
>
> diff --git
> a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/plugin/RegistryReader.java
> b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/plugin/RegistryReader.java
>
> index 9666a50..bf098c3 100644
> ---
> a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/plugin/RegistryReader.java
> +++
> b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/plugin/RegistryReader.java
> @@ -24,9 +24,11 @@ import org.eclipse.core.runtime.IExtensionRegistry;
> import org.eclipse.core.runtime.IRegistryChangeEvent;
> import org.eclipse.core.runtime.IRegistryChangeListener;
> import org.eclipse.emf.common.CommonPlugin;
> +import org.eclipse.emf.common.util.EList;
> import org.eclipse.emf.common.util.URI;
> import org.eclipse.emf.common.util.WrappedException;
> import org.eclipse.emf.ecore.EFactory;
> +import org.eclipse.emf.ecore.EObject;
> import org.eclipse.emf.ecore.EPackage;
> import org.eclipse.emf.ecore.EcorePackage;
> import org.eclipse.emf.ecore.resource.Resource;
> @@ -244,7 +246,11 @@ public abstract class RegistryReader
> }
> else
> {
> - return (EPackage)
> EcoreUtil.getObjectByType(resourceSet.getResource(locationURI,
> true).getContents(), EcorePackage.Literals.EPACKAGE);
> + Resource r = resourceSet.getResource(locationURI, true);
> + if (r != null)
> + return (EPackage)
> EcoreUtil.getObjectByType(r.getContents(),
> EcorePackage.Literals.EPACKAGE);
> + else
> + throw new RuntimeException("No EPackage found at:
> " + locationURI);
> }
> }
> else
>
>
> Basically, the original code assumes that resourceSet.getResource(...)
> never returns null. AFAIK, there is no such guarantee at the point in
> the logic.
This sounds more likely to be a problem with no resource factory being
registered for *.xcore. https://bugs.eclipse.org/bugs/show_bug.cgi?id=453329
>
> With this NPE vulnerability aside, we are left with the problem: how
> could a ResourceSet have a null resource?
>
> This should not happen but it obviously does in this case.
>
> The problem is really due to concurrent calls to
> ResourceSet.add(Resource) because the default implementation (i.e.
> ResourceSetImpl) is not thread-safe for concurrent modification.
> I managed to work around the problem by synchronizing calls to
> ResourceSetImpl::add(Resource):
No, resource sets aren't designed or intended to be thread safe and
adding synchronization will be a source of deadlock. Better to look at
something like
org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.getEPackage()
and make sure that it hold a lock on the resource set rather than start
sprinkling synchronization into all resource set implementations.
>
>
> diff --git
> a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/resource/impl/ResourceSetImpl.java
> b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/resource/impl/ResourceSetImpl.java
>
> index 6f896e8..9792542 100644
> ---
> a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/resource/impl/ResourceSetImpl.java
> +++
> b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/resource/impl/ResourceSetImpl.java
> @@ -432,7 +432,9 @@ public class ResourceSetImpl extends NotifierImpl
> implements ResourceSet
> if (resourceFactory != null)
> {
> Resource result = resourceFactory.createResource(uri);
> - getResources().add(result);
> + if (result != null) {
> + getResources().add(result);
> + }
> return result;
> }
> else
> @@ -609,6 +611,14 @@ public class ResourceSetImpl extends NotifierImpl
> implements ResourceSet
> {
> return size <= 4 ? super.contains(object) : object instanceof
> Resource && ((Resource)object).getResourceSet() == ResourceSetImpl.this;
> }
> +
> + @Override
> + public boolean add(E object) {
> + synchronized(this) {
> + return super.add(object);
> + }
> + }
> + }
>
>
> The evidence that this workaround is effective is that if I comment
> out the synchronized guard in the call to super.add(object), then I
> get NPEs on 2 threads at initialization.
> Has anyone encountered this problem before?
No.
>
> Is there a test case that involves plugins that register dynamic
> metamodels?
No.
>
> If yes, I'd like to see if I can reproduce this problem in a simpler
> environment by opening the Eclipse QVTO metamodel registry view and an
> Eclipse QVTO editor.
> This seems to be enough to concurrent threads that will initialize the
> EMF EPackage registry and therefore force adding metamodel resources
> to the same ResourceSet.
We'd need a new test case, but it's pretty clear from inspection that
org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.getEPackage()
isn't thread safe.
>
> On the other hand, it is rather interesting that these NPEs have
> systematically happened during the initialization of XCore even though
> the examples I made do not involve XCore's metamodels (except for the
> Eclipse QVTO Metamodel Registry view which shows all registered
> metamodels -- static & dynamic)
Yes, that's a little odd. I do get the sense that something
(MetamodelRegistry.toEPackageRegistry()?) is aggressively loading all
registered models.
>
> - Nicolas.


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)? [message #1518908 is a reply to message #1518534] Sat, 20 December 2014 10:10 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi Nicolas

EMF has a very sensible thread safety policy: [1]

"EMF can safely be used in multi-threaded environments; however, EMF
does not, itself, ensure thread-safety in application model
implementations. Data structures are unsynchronized, for performance and
to avoid potential deadlock situations. The expectation is that a
complete instance of the model (including resources and resource set, if
present) should only be accessed by one thread at a time, and that the
synchronization should be provided by the application at a higher level. "

This worked well for many years. Recently EMF UI tooling has been
improving with facilities such as live validation without full
consideration of the consequent elevation of EMF single-threaded tools
to the status of applications.

This is particularly serious for UML where profiles are loaded lazily.
Consequently what an EMF developer might consider to be a simple short
sharp activity is not simple at all since what appeared to be a trivial
eGet() might actually involve loading 10 UML models and a ResourceSet
modification. I have raised at least a couple of CME bugs that this
laziness has exposed.

This can be differently serious when OCL enrichment is used, since once
again a simple eGet() may involve OCL parsing, model loading and
evaluation of the relevant OCL delegate body.

There are a couple of recent bug fixes that mitigate these hazards.

Your problem seems slightly adjacent. At the simplest level, if you are
not using Xcore then why are Xcore resources being loaded? I vaguely
recall raising a QVTo bug to the effect that a registry scan was being
over-enthusiastic; it can easily cause all installed model plugins o be
activated.

I recommend investigating why QVTo is allowing Xcore to incur
non-trivial costs and identifying what the concurrent activities are and
why they are not synchronized. A few years ago a validation hazard was
resolved by synchronizing on the ResourceSet, but I am not aware of any
documentation to establish a more general inter-thread design approach.

Regards

Ed Willink




[1] https://wiki.eclipse.org/EMF/FAQ#Is_EMF_thread-safe.3F



On 20/12/2014 05:06, Nicolas Rouquette wrote:
> Until recently, we haven't had to register dynamic metamodels in our
> Eclipse IDE for QVTO development. We could instead register metamodels
> via their implementations. As far as using the Eclipse IDE to compile
> source *.qvto files into executable *.qvtox files, the Eclipse QVTO
> compiler only cares that all metamodels involved have been properly
> registered. Using the implementations was the simplest way to go. This
> worked very well for us for several years until now...
>
> Now, we have to deal with fundamentally different versions of metamodels
> (UML 2.4 and UML 2.5) both of which have dependencies on the same
> metamodels. The conventional approach would lead to nasty jar conflicts.
> To be fair, these different versions are not designed to coexist in the
> same JVM! Since for Eclipse QVTO development we don't technically need
> to "execute" the metamodel, I thought that I could instead register all
> of these metamodels as dynamic -- i.e., *.ecore, no java.
>
> In principle it should work (It's been described in several places,
> including the EMF book). However, I've encountered some problems at
> Eclipse initialization.
>
> I'm using Eclipse Luna with a lot of EMF-related technology (XCore,
> QVTO, DiffMerge, EASE, ....) Too much to extract a simple test case but
> I think the problem is fairly simple.
>
> Basically, there are multiple Eclipse views that, at startup, query the
> EMF EPackage registry. In the stack traces below, there are 2 views
> involved:
>
> - the Eclipse QVTO Metamodel Registry view (it shows all the registered
> metamodels)
> - an Eclipse QVTO editor (which makes references to several registered
> metamodels)
>
> Both initializations trigger NPEs.
>
>
> Daemon Thread [org.eclipse.m2m.internal.qvt.oml.editor.ui.QvtReconciler]
> (Suspended (exception NullPointerException))
> owns: XcoreResource (id=113)
> XcoreJavaProjectProvider.getJavaProject(ResourceSet) line: 97
> XcoreJavaProjectProvider.getClassLoader(ResourceSet) line: 124
> XcoreEcoreBuilder.getEPackage(XPackage) line: 195
> XcoreModelAssociator.installDerivedState(DerivedStateAwareResource,
> boolean) line: 92
> XcoreResource(DerivedStateAwareResource).installDerivedState(boolean) line: 159
> XcoreResource(BatchLinkableResource).getContents() line: 133
> RegistryReader$EPackageDescriptor$Dynamic.getEPackage() line: 251
> EmfMetamodelDesc.getModel() line: 61
> EmfMetamodelDesc.getLoadStatus() line: 91
> MetamodelRegistry.toEPackageRegistry() line: 95
> CompilerUtils.getEPackageRegistry(URI, IMetamodelRegistryProvider)
> line: 107
> QVTOCompiler.getEPackageRegistry(URI) line: 529
> QVTOCompiler.parse(UnitProxy, QvtCompilerOptions) line: 233
> QVTOCompiler.doCompile(UnitProxy, QvtCompilerOptions, Monitor)
> line: 369
> QVTOCompiler.compileSingleFile(UnitProxy, QvtCompilerOptions,
> Monitor) line: 326
> QVTOCompiler.compile(UnitProxy[], QvtCompilerOptions, Monitor)
> line: 211
> QVTOCompiler.compile(UnitProxy, QvtCompilerOptions, Monitor) line: 224
> QvtCompilerFacade.compile(ITextEditor, IDocument,
> QvtCompilerOptions, IProgressMonitor) line: 77
> QvtReconcilingStrategy.getCompilationResult(boolean) line: 90
> QvtReconcilingStrategy.reconcileInternal() line: 74
> QvtReconcilingStrategy.initialReconcile() line: 62
> QvtReconciler(MonoReconciler).initialProcess() line: 105
> AbstractReconciler$BackgroundThread.run() line: 173
>
>
> The Eclipse QVTO Metamodel Registry view:
>
>
> Thread [main] (Suspended (exception NullPointerException))
> owns: XcoreResource (id=106)
> XcoreJavaProjectProvider.getJavaProject(ResourceSet) line: 97
> XcoreJavaProjectProvider.getClassLoader(ResourceSet) line: 124
> XcoreEcoreBuilder.getEPackage(XPackage) line: 195
> XcoreModelAssociator.installDerivedState(DerivedStateAwareResource,
> boolean) line: 92
> XcoreResource(DerivedStateAwareResource).installDerivedState(boolean) line: 159
> XcoreResource(BatchLinkableResource).getContents() line: 133
> RegistryReader$EPackageDescriptor$Dynamic.getEPackage() line: 251
> EmfMetamodelDesc.getModel() line: 61
> MetamodelBrowserView$3(MetamodelBrowser).doCreateInput() line: 502
> MetamodelBrowser$5.run() line: 473
> BusyIndicator.showWhile(Display, Runnable) line: 70
> MetamodelBrowserView$3(MetamodelBrowser).createInput() line: 471
> MetamodelBrowserView$3(MetamodelBrowser).<init>(Composite, int)
> line: 168
> MetamodelBrowserView$3(MetamodelBrowser).<init>(Composite) line: 145
> MetamodelBrowserView$3.<init>(MetamodelBrowserView, Composite)
> line: 108
> MetamodelBrowserView.createPartControl(Composite) line: 108
> CompatibilityView(CompatibilityPart).createPartControl(IWorkbenchPart, Composite) line: 141
> CompatibilityView.createPartControl(IWorkbenchPart, Composite)
> line: 155
> CompatibilityView(CompatibilityPart).create() line: 327
> NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line:
> not available [native method]
> NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62
> DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
> Method.invoke(Object, Object...) line: 483
> MethodRequestor.execute() line: 55
> InjectorImpl.processAnnotated(Class<Annotation>, Object, Class<?>,
> PrimaryObjectSupplier, PrimaryObjectSupplier, ArrayList<Class<?>>) line:
> 888
> InjectorImpl.processAnnotated(Class<Annotation>, Object, Class<?>,
> PrimaryObjectSupplier, PrimaryObjectSupplier, ArrayList<Class<?>>) line:
> 869
> InjectorImpl.inject(Object, PrimaryObjectSupplier,
> PrimaryObjectSupplier) line: 120
> InjectorImpl.internalMake(Class<?>, PrimaryObjectSupplier,
> PrimaryObjectSupplier) line: 337
> InjectorImpl.make(Class<T>, PrimaryObjectSupplier) line: 258
> ContextInjectionFactory.make(Class<T>, IEclipseContext) line: 162
> ReflectionContributionFactory.createFromBundle(Bundle,
> IEclipseContext, IEclipseContext, URI) line: 104
> ReflectionContributionFactory.doCreate(String, IEclipseContext,
> IEclipseContext) line: 73
> ReflectionContributionFactory.create(String, IEclipseContext) line: 55
> ContributedPartRenderer.createWidget(MUIElement, Object) line: 127
> PartRenderingEngine.createWidget(MUIElement, Object) line: 983
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 662
> PartRenderingEngine$6.run() line: 547
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement, Object, IEclipseContext)
> line: 531
> ElementReferenceRenderer.createWidget(MUIElement, Object) line: 69
> PartRenderingEngine.createWidget(MUIElement, Object) line: 983
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 662
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line:
> 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> StackRenderer.showTab(MUIElement) line: 1250
> StackRenderer(LazyStackRenderer).postProcess(MUIElement) line: 100
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 678
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line:
> 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68
> SashRenderer.processContents(MElementContainer<MUIElement>) line: 185
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line:
> 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68
> SashRenderer.processContents(MElementContainer<MUIElement>) line: 185
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line:
> 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68
> SashRenderer.processContents(MElementContainer<MUIElement>) line: 185
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line:
> 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> PerspectiveRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68
> PerspectiveRenderer.processContents(MElementContainer<MUIElement>)
> line: 49
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line:
> 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> PerspectiveStackRenderer.showTab(MUIElement) line: 103
> PerspectiveStackRenderer(LazyStackRenderer).postProcess(MUIElement)
> line: 100
> PerspectiveStackRenderer.postProcess(MUIElement) line: 77
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 678
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line:
> 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68
> SashRenderer.processContents(MElementContainer<MUIElement>) line: 185
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line:
> 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> WBWRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68
> WBWRenderer.processContents(MElementContainer<MUIElement>) line: 664
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line:
> 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> PartRenderingEngine$9.run() line: 1078
> Realm.runWithDefault(Realm, Runnable) line: 332
> PartRenderingEngine.run(MApplicationElement, IEclipseContext) line:
> 1032
> E4Workbench.createAndRunUI(MApplicationElement) line: 148
> Workbench$5.run() line: 636
> Realm.runWithDefault(Realm, Runnable) line: 332
> Workbench.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 579
> PlatformUI.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 150
> IDEApplication.start(IApplicationContext) line: 135
> EclipseAppHandle.run(Object) line: 196
> EclipseAppLauncher.runApplication(Object) line: 134
> EclipseAppLauncher.start(Object) line: 104
> EclipseStarter.run(Object) line: 380
> EclipseStarter.run(String[], Runnable) line: 235
> NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line:
> not available [native method]
> NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62
> DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
> Method.invoke(Object, Object...) line: 483
> Main.invokeFramework(String[], URL[]) line: 648
> Main.basicRun(String[]) line: 603
> Main.run(String[]) line: 1465
> Main.main(String[]) line: 1438
>
>
> These 2 threads are trying to register the same EPackage: xcore.lang
>
> The NPE is caused by the fact that the ResourceSet's resources contains
> a NULL!
>
>
> for (Resource resource : resourceSet.getResources())
> {
> URI uri = resource.getURI(); // NPE because resource is null!
> ...
> }
>
>
> There was a misleading NPE that turns out to be a minor vulnerability in
> the EMF RegistryReader:
>
>
> diff --git
> a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/plugin/RegistryReader.java
> b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/plugin/RegistryReader.java
>
> index 9666a50..bf098c3 100644
> ---
> a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/plugin/RegistryReader.java
>
> +++
> b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/plugin/RegistryReader.java
>
> @@ -24,9 +24,11 @@ import org.eclipse.core.runtime.IExtensionRegistry;
> import org.eclipse.core.runtime.IRegistryChangeEvent;
> import org.eclipse.core.runtime.IRegistryChangeListener;
> import org.eclipse.emf.common.CommonPlugin;
> +import org.eclipse.emf.common.util.EList;
> import org.eclipse.emf.common.util.URI;
> import org.eclipse.emf.common.util.WrappedException;
> import org.eclipse.emf.ecore.EFactory;
> +import org.eclipse.emf.ecore.EObject;
> import org.eclipse.emf.ecore.EPackage;
> import org.eclipse.emf.ecore.EcorePackage;
> import org.eclipse.emf.ecore.resource.Resource;
> @@ -244,7 +246,11 @@ public abstract class RegistryReader
> }
> else
> {
> - return (EPackage)
> EcoreUtil.getObjectByType(resourceSet.getResource(locationURI,
> true).getContents(), EcorePackage.Literals.EPACKAGE);
> + Resource r = resourceSet.getResource(locationURI, true);
> + if (r != null)
> + return (EPackage)
> EcoreUtil.getObjectByType(r.getContents(), EcorePackage.Literals.EPACKAGE);
> + else
> + throw new RuntimeException("No EPackage found at: "
> + locationURI);
> }
> }
> else
>
>
> Basically, the original code assumes that resourceSet.getResource(...)
> never returns null. AFAIK, there is no such guarantee at the point in
> the logic.
>
> With this NPE vulnerability aside, we are left with the problem: how
> could a ResourceSet have a null resource?
>
> This should not happen but it obviously does in this case.
>
> The problem is really due to concurrent calls to
> ResourceSet.add(Resource) because the default implementation (i.e.
> ResourceSetImpl) is not thread-safe for concurrent modification.
> I managed to work around the problem by synchronizing calls to
> ResourceSetImpl::add(Resource):
>
>
> diff --git
> a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/resource/impl/ResourceSetImpl.java
> b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/resource/impl/ResourceSetImpl.java
>
> index 6f896e8..9792542 100644
> ---
> a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/resource/impl/ResourceSetImpl.java
>
> +++
> b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/resource/impl/ResourceSetImpl.java
>
> @@ -432,7 +432,9 @@ public class ResourceSetImpl extends NotifierImpl
> implements ResourceSet
> if (resourceFactory != null)
> {
> Resource result = resourceFactory.createResource(uri);
> - getResources().add(result);
> + if (result != null) {
> + getResources().add(result);
> + }
> return result;
> }
> else
> @@ -609,6 +611,14 @@ public class ResourceSetImpl extends NotifierImpl
> implements ResourceSet
> {
> return size <= 4 ? super.contains(object) : object instanceof
> Resource && ((Resource)object).getResourceSet() == ResourceSetImpl.this;
> }
> +
> + @Override
> + public boolean add(E object) {
> + synchronized(this) {
> + return super.add(object);
> + }
> + }
> + }
>
>
> The evidence that this workaround is effective is that if I comment out
> the synchronized guard in the call to super.add(object), then I get NPEs
> on 2 threads at initialization.
> Has anyone encountered this problem before?
>
> Is there a test case that involves plugins that register dynamic
> metamodels?
>
> If yes, I'd like to see if I can reproduce this problem in a simpler
> environment by opening the Eclipse QVTO metamodel registry view and an
> Eclipse QVTO editor.
> This seems to be enough to concurrent threads that will initialize the
> EMF EPackage registry and therefore force adding metamodel resources to
> the same ResourceSet.
>
> On the other hand, it is rather interesting that these NPEs have
> systematically happened during the initialization of XCore even though
> the examples I made do not involve XCore's metamodels (except for the
> Eclipse QVTO Metamodel Registry view which shows all registered
> metamodels -- static & dynamic)
>
> - Nicolas.
Re: Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)? [message #1519740 is a reply to message #1518908] Sat, 20 December 2014 21:26 Go to previous messageGo to next message
Nicolas Rouquette is currently offline Nicolas RouquetteFriend
Messages: 157
Registered: July 2009
Senior Member
There seem to be several problems involved.

1) no resource factory registered for *.xcore

https://bugs.eclipse.org/bugs/show_bug.cgi?id=453329

Jonas' last comment is definitely relevant since both QVTO's Metamodel Browser view and QVTO's Compiler do browse the EPackage registry for metamodels.

Quote:

Added Ed for information, because this problem might affect other frameworks too, which browse the package registry.


How do I tell if this bug affects me?

The ResourceSet involved -- i.e.: org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.resourceSet -- does not have any resource factory.
I don't understand how having or not a resource factory for XCore.lang per se would have such a particular impact on a small fraction of completely unrelated metamodels!

This bug may be a factor but it seems that it's not enough.
There must be something else involved.

2) vulnerability to NPE

Shouldn't Eclipse initialize cleanly without any NPEs?

Since ResourceSet.getResource() may return null, the code in org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.getEPackage()
will trip an NPE in precisely such case:

return (EPackage) EcoreUtil.getObjectByType(resourceSet.getResource(locationURI, true).getContents(), EcorePackage.Literals.EPACKAGE);


I really would like to see this fixed -- it's annoying to get these NPEs when launching Eclispe under the debugger.

Is this enough to cause the problems? Again, it may be a symptom but it does not seem to be sufficient by itself.

3) concurrency problems.

>> The problem is really due to concurrent calls to
>> ResourceSet.add(Resource) because the default implementation (i.e.
>> ResourceSetImpl) is not thread-safe for concurrent modification.
>> I managed to work around the problem by synchronizing calls to
>> ResourceSetImpl::add(Resource):
> No, resource sets aren't designed or intended to be thread safe and
> adding synchronization will be a source of deadlock. Better to look at
> something like
> org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.getEPackage()
> and make sure that it hold a lock on the resource set rather than start
> sprinkling synchronization into all resource set implementations.

I don't understand.

If resource sets are not designed nor intended to be thread safe, then doesn't this imply that there should be at most 1 thread modifying a given resource set at any time?
If it does, then why would adding synchronization using the resource set itself be a source of deadlock?

In examining the code involved in the stack trace, I noticed that there is in fact synchronization in a different method:

org.eclipse.xtext.xbase.resource.BatchLinkableResource.getContents():

	public EList<EObject> getContents() {
		synchronized (getLock()) {
			if (isLoaded && !isLoading && !isInitializing && !isUpdating && !fullyInitialized) {
				try {
					eSetDeliver(false);
					installDerivedState(false);
				} finally {
					eSetDeliver(true);
				}
			}
			return doGetContents();
		}
	}


In this case -- i.e., the resource set is: org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.resourceSet
Since it isn't an ISynchronizable, getLock() returns 'this' -- i.e. the resource itself.

	/**
	 * Returns the lock of the owning {@link ResourceSet}, if it exposes such a lock.
	 * Otherwise this resource itself is used as the lock context.
	 */
	/* @NonNull */
	public Object getLock() {
		ResourceSet resourceSet = getResourceSet();
		if (resourceSet instanceof ISynchronizable<?>) {
			return ((ISynchronizable<?>) resourceSet).getLock();
		}
		return this;
	}


What happens then?

Well, we can have multiple threads that will concurrently attempt to initialize XCore's metamodels but with *different* Resource objects -- i.e. different Resources loaded from uri='platform:/plugin/org.eclipse.emf.ecore.xcore.lib/model/XcoreLang.xcore'

Here are some examples:

Daemon Thread [org.eclipse.m2m.internal.qvt.oml.editor.ui.QvtReconciler] (Suspended)	
	owns: XcoreResource  (id=172)	
	XcoreResource(BatchLinkableResource).getContents() line: 130	
	XcoreResource(XtextResource).updateInternalState(IParseResult) line: 253	
	XcoreResource(DerivedStateAwareResource).updateInternalState(IParseResult) line: 101	
	XcoreResource(XtextResource).updateInternalState(IParseResult, IParseResult) line: 248	
	XcoreResource(DerivedStateAwareResource).updateInternalState(IParseResult, IParseResult) line: 93	
	XcoreResource(XtextResource).doLoad(InputStream, Map<?,?>) line: 161	
	XcoreResource(LazyLinkingResource).doLoad(InputStream, Map<?,?>) line: 100	
	XcoreResource(ResourceImpl).load(InputStream, Map<?,?>) line: 1518	
	XcoreResource(ResourceImpl).load(Map<?,?>) line: 1297	
	RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).demandLoad(Resource) line: 259	
	RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).demandLoadHelper(Resource) line: 274	
	RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).getResource(URI, boolean) line: 406	
	RegistryReader$EPackageDescriptor$Dynamic.getEPackage() line: 249	
	EmfMetamodelDesc.getModel() line: 61	
	EmfMetamodelDesc.getLoadStatus() line: 91	
	MetamodelRegistry.toEPackageRegistry() line: 95	
	CompilerUtils.getEPackageRegistry(URI, IMetamodelRegistryProvider) line: 107	
	QVTOCompiler.getEPackageRegistry(URI) line: 529	
	QVTOCompiler.parse(UnitProxy, QvtCompilerOptions) line: 233	
	QVTOCompiler.doCompile(UnitProxy, QvtCompilerOptions, Monitor) line: 369	
	QVTOCompiler.compileSingleFile(UnitProxy, QvtCompilerOptions, Monitor) line: 326	
	QVTOCompiler.compile(UnitProxy[], QvtCompilerOptions, Monitor) line: 211	
	QVTOCompiler.compile(UnitProxy, QvtCompilerOptions, Monitor) line: 224	
	QvtCompilerFacade.compile(ITextEditor, IDocument, QvtCompilerOptions, IProgressMonitor) line: 77	
	QvtReconcilingStrategy.getCompilationResult(boolean) line: 90	
	QvtReconcilingStrategy.reconcileInternal() line: 74	
	QvtReconcilingStrategy.initialReconcile() line: 62	
	QvtReconciler(MonoReconciler).initialProcess() line: 105	
	AbstractReconciler$BackgroundThread.run() line: 173	


and:

Daemon Thread [org.eclipse.m2m.internal.qvt.oml.editor.ui.QvtReconciler] (Suspended)	
	owns: XcoreResource  (id=186)	
	XcoreResource(BatchLinkableResource).getContents() line: 130	
	XcoreResource(XtextResource).updateInternalState(IParseResult) line: 253	
	XcoreResource(DerivedStateAwareResource).updateInternalState(IParseResult) line: 101	
	XcoreResource(XtextResource).updateInternalState(IParseResult, IParseResult) line: 248	
	XcoreResource(DerivedStateAwareResource).updateInternalState(IParseResult, IParseResult) line: 93	
	XcoreResource(XtextResource).doLoad(InputStream, Map<?,?>) line: 161	
	XcoreResource(LazyLinkingResource).doLoad(InputStream, Map<?,?>) line: 100	
	XcoreResource(ResourceImpl).load(InputStream, Map<?,?>) line: 1518	
	XcoreResource(ResourceImpl).load(Map<?,?>) line: 1297	
	RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).demandLoad(Resource) line: 259	
	RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).demandLoadHelper(Resource) line: 274	
	RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).getResource(URI, boolean) line: 406	
	RegistryReader$EPackageDescriptor$Dynamic.getEPackage() line: 249	
	EmfMetamodelDesc.getModel() line: 61	
	EmfMetamodelDesc.getLoadStatus() line: 91	
	MetamodelRegistry.toEPackageRegistry() line: 95	
	CompilerUtils.getEPackageRegistry(URI, IMetamodelRegistryProvider) line: 107	
	QVTOCompiler.getEPackageRegistry(URI) line: 529	
	QVTOCompiler.parse(UnitProxy, QvtCompilerOptions) line: 233	
	QVTOCompiler.doCompile(UnitProxy, QvtCompilerOptions, Monitor) line: 369	
	QVTOCompiler.compileSingleFile(UnitProxy, QvtCompilerOptions, Monitor) line: 326	
	QVTOCompiler.compile(UnitProxy[], QvtCompilerOptions, Monitor) line: 211	
	QVTOCompiler.compile(UnitProxy, QvtCompilerOptions, Monitor) line: 224	
	QvtCompilerFacade.compile(ITextEditor, IDocument, QvtCompilerOptions, IProgressMonitor) line: 77	
	QvtReconcilingStrategy.getCompilationResult(boolean) line: 90	
	QvtReconcilingStrategy.reconcileInternal() line: 74	
	QvtReconcilingStrategy.initialReconcile() line: 62	
	QvtReconciler(MonoReconciler).initialProcess() line: 105	
	AbstractReconciler$BackgroundThread.run() line: 173	


and:

Daemon Thread [org.eclipse.m2m.internal.qvt.oml.editor.ui.QvtReconciler] (Suspended)	
	owns: XcoreResource  (id=190)	
	XcoreResource(BatchLinkableResource).getContents() line: 130	
	XcoreResource(XtextResource).updateInternalState(IParseResult) line: 253	
	XcoreResource(DerivedStateAwareResource).updateInternalState(IParseResult) line: 101	
	XcoreResource(XtextResource).updateInternalState(IParseResult, IParseResult) line: 248	
	XcoreResource(DerivedStateAwareResource).updateInternalState(IParseResult, IParseResult) line: 93	
	XcoreResource(XtextResource).doLoad(InputStream, Map<?,?>) line: 161	
	XcoreResource(LazyLinkingResource).doLoad(InputStream, Map<?,?>) line: 100	
	XcoreResource(ResourceImpl).load(InputStream, Map<?,?>) line: 1518	
	XcoreResource(ResourceImpl).load(Map<?,?>) line: 1297	
	RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).demandLoad(Resource) line: 259	
	RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).demandLoadHelper(Resource) line: 274	
	RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).getResource(URI, boolean) line: 406	
	RegistryReader$EPackageDescriptor$Dynamic.getEPackage() line: 249	
	EmfMetamodelDesc.getModel() line: 61	
	EmfMetamodelDesc.getLoadStatus() line: 91	
	MetamodelRegistry.toEPackageRegistry() line: 95	
	CompilerUtils.getEPackageRegistry(URI, IMetamodelRegistryProvider) line: 107	
	QVTOCompiler.getEPackageRegistry(URI) line: 529	
	QVTOCompiler.parse(UnitProxy, QvtCompilerOptions) line: 233	
	QVTOCompiler.doCompile(UnitProxy, QvtCompilerOptions, Monitor) line: 369	
	QVTOCompiler.compileSingleFile(UnitProxy, QvtCompilerOptions, Monitor) line: 326	
	QVTOCompiler.compile(UnitProxy[], QvtCompilerOptions, Monitor) line: 211	
	QVTOCompiler.compile(UnitProxy, QvtCompilerOptions, Monitor) line: 224	
	QvtCompilerFacade.compile(ITextEditor, IDocument, QvtCompilerOptions, IProgressMonitor) line: 77	
	QvtReconcilingStrategy.getCompilationResult(boolean) line: 90	
	QvtReconcilingStrategy.reconcileInternal() line: 74	
	QvtReconcilingStrategy.initialReconcile() line: 62	
	QvtReconciler(MonoReconciler).initialProcess() line: 105	
	AbstractReconciler$BackgroundThread.run() line: 173	


and:

Thread [main] (Suspended)	
	owns: XcoreResource  (id=126)	
	XcoreResource(BatchLinkableResource).getContents() line: 130	
	XcoreResource(XtextResource).updateInternalState(IParseResult) line: 253	
	XcoreResource(DerivedStateAwareResource).updateInternalState(IParseResult) line: 101	
	XcoreResource(XtextResource).updateInternalState(IParseResult, IParseResult) line: 248	
	XcoreResource(DerivedStateAwareResource).updateInternalState(IParseResult, IParseResult) line: 93	
	XcoreResource(XtextResource).doLoad(InputStream, Map<?,?>) line: 161	
	XcoreResource(LazyLinkingResource).doLoad(InputStream, Map<?,?>) line: 100	
	XcoreResource(ResourceImpl).load(InputStream, Map<?,?>) line: 1518	
	XcoreResource(ResourceImpl).load(Map<?,?>) line: 1297	
	RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).demandLoad(Resource) line: 259	
	RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).demandLoadHelper(Resource) line: 274	
	RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).getResource(URI, boolean) line: 406	
	RegistryReader$EPackageDescriptor$Dynamic.getEPackage() line: 249	
	EmfMetamodelDesc.getModel() line: 61	
	MetamodelBrowserView$3(MetamodelBrowser).doCreateInput() line: 502	
	MetamodelBrowser$5.run() line: 473	
	BusyIndicator.showWhile(Display, Runnable) line: 70	
	MetamodelBrowserView$3(MetamodelBrowser).createInput() line: 471	
	MetamodelBrowserView$3(MetamodelBrowser).<init>(Composite, int) line: 168	
	MetamodelBrowserView$3(MetamodelBrowser).<init>(Composite) line: 145	
	MetamodelBrowserView$3.<init>(MetamodelBrowserView, Composite) line: 108	
	MetamodelBrowserView.createPartControl(Composite) line: 108	
	CompatibilityView(CompatibilityPart).createPartControl(IWorkbenchPart, Composite) line: 141	
	CompatibilityView.createPartControl(IWorkbenchPart, Composite) line: 155	
	CompatibilityView(CompatibilityPart).create() line: 327	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43	
	Method.invoke(Object, Object...) line: 483	
	MethodRequestor.execute() line: 55	
	InjectorImpl.processAnnotated(Class<Annotation>, Object, Class<?>, PrimaryObjectSupplier, PrimaryObjectSupplier, ArrayList<Class<?>>) line: 888	
	InjectorImpl.processAnnotated(Class<Annotation>, Object, Class<?>, PrimaryObjectSupplier, PrimaryObjectSupplier, ArrayList<Class<?>>) line: 869	
	InjectorImpl.inject(Object, PrimaryObjectSupplier, PrimaryObjectSupplier) line: 120	
	InjectorImpl.internalMake(Class<?>, PrimaryObjectSupplier, PrimaryObjectSupplier) line: 337	
	InjectorImpl.make(Class<T>, PrimaryObjectSupplier) line: 258	
	ContextInjectionFactory.make(Class<T>, IEclipseContext) line: 162	
	ReflectionContributionFactory.createFromBundle(Bundle, IEclipseContext, IEclipseContext, URI) line: 104	
	ReflectionContributionFactory.doCreate(String, IEclipseContext, IEclipseContext) line: 73	
	ReflectionContributionFactory.create(String, IEclipseContext) line: 55	
	ContributedPartRenderer.createWidget(MUIElement, Object) line: 127	
	PartRenderingEngine.createWidget(MUIElement, Object) line: 983	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 662	
	PartRenderingEngine$6.run() line: 547	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement, Object, IEclipseContext) line: 531	
	ElementReferenceRenderer.createWidget(MUIElement, Object) line: 69	
	PartRenderingEngine.createWidget(MUIElement, Object) line: 983	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 662	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	StackRenderer.showTab(MUIElement) line: 1250	
	StackRenderer(LazyStackRenderer).postProcess(MUIElement) line: 100	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 678	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68	
	SashRenderer.processContents(MElementContainer<MUIElement>) line: 185	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 674	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68	
	SashRenderer.processContents(MElementContainer<MUIElement>) line: 185	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 674	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68	
	SashRenderer.processContents(MElementContainer<MUIElement>) line: 185	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 674	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	PerspectiveRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68	
	PerspectiveRenderer.processContents(MElementContainer<MUIElement>) line: 49	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 674	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	PerspectiveStackRenderer.showTab(MUIElement) line: 103	
	PerspectiveStackRenderer(LazyStackRenderer).postProcess(MUIElement) line: 100	
	PerspectiveStackRenderer.postProcess(MUIElement) line: 77	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 678	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68	
	SashRenderer.processContents(MElementContainer<MUIElement>) line: 185	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 674	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	WBWRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>) line: 68	
	WBWRenderer.processContents(MElementContainer<MUIElement>) line: 664	
	PartRenderingEngine.safeCreateGui(MUIElement, Object, IEclipseContext) line: 674	
	PartRenderingEngine.safeCreateGui(MUIElement) line: 766	
	PartRenderingEngine.access$2(PartRenderingEngine, MUIElement) line: 737	
	PartRenderingEngine$7.run() line: 731	
	SafeRunner.run(ISafeRunnable) line: 42	
	PartRenderingEngine.createGui(MUIElement) line: 715	
	PartRenderingEngine$9.run() line: 1078	
	Realm.runWithDefault(Realm, Runnable) line: 332	
	PartRenderingEngine.run(MApplicationElement, IEclipseContext) line: 1032	
	E4Workbench.createAndRunUI(MApplicationElement) line: 148	
	Workbench$5.run() line: 636	
	Realm.runWithDefault(Realm, Runnable) line: 332	
	Workbench.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 579	
	PlatformUI.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 150	
	IDEApplication.start(IApplicationContext) line: 135	
	EclipseAppHandle.run(Object) line: 196	
	EclipseAppLauncher.runApplication(Object) line: 134	
	EclipseAppLauncher.start(Object) line: 104	
	EclipseStarter.run(Object) line: 380	
	EclipseStarter.run(String[], Runnable) line: 235	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43	
	Method.invoke(Object, Object...) line: 483	
	Main.invokeFramework(String[], URL[]) line: 648	
	Main.basicRun(String[]) line: 603	
	Main.run(String[]) line: 1465	
	Main.main(String[]) line: 1438	


Even though I stopped all of these threads, the RegistryReader's ResourceSet is already compromised:

resourceSet org.eclipse.emf.ecore.plugin.RegistryReader$EPackageDescriptor$Dynamic$1 (id=128)

org.eclipse.emf.ecore.plugin.RegistryReader$EPackageDescriptor$Dynamic$1@50ad5eb8 resources=[org.eclipse.emf.ecore.xcore.resource.XcoreResource@e11cb3b uri='platform:/plugin/org.eclipse.emf.ecore.xcore.lib/model/XcoreLang.xcore', null, null, org.eclipse.emf.ecore.xcore.resource.XcoreResource@6e716c17 uri='platform:/plugin/org.eclipse.emf.ecore.xcore.lib/model/XcoreLang.xcore']

There are already 2 null values and XcoreLang appears twice already!

Even though it may not be the best way to fix the problem, it's interesting that adding a synchronization on ResourceSetImpl.add(Resource) suffices to avoid this problem (it could cause others as Ed M pointed out).

- Nicolas.
Re: Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)? [message #1519861 is a reply to message #1519740] Sat, 20 December 2014 23:02 Go to previous messageGo to next message
Nicolas Rouquette is currently offline Nicolas RouquetteFriend
Messages: 157
Registered: July 2009
Senior Member
As Ed M observed, adding synchronization to ResourceSetImple.add(Resource)
would have wide ranging impacts. Instead, I added synchronization
to the mutating operations of RegistryReader's dynamic resourceSet class.

Based on limited tests, this seems to work fine; at least, I don't get any NPEs on Eclipse startup and the EPackage registry doesn't have any errors.

diff --git a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/plugin/RegistryReader.java b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/plugin/RegistryReader.java
index 9666a50..23b4c26 100644
--- a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/plugin/RegistryReader.java
+++ b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/plugin/RegistryReader.java
@@ -24,9 +24,11 @@ import org.eclipse.core.runtime.IExtensionRegistry;
 import org.eclipse.core.runtime.IRegistryChangeEvent;
 import org.eclipse.core.runtime.IRegistryChangeListener;
 import org.eclipse.emf.common.CommonPlugin;
+import org.eclipse.emf.common.util.EList;
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.common.util.WrappedException;
 import org.eclipse.emf.ecore.EFactory;
+import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EPackage;
 import org.eclipse.emf.ecore.EcorePackage;
 import org.eclipse.emf.ecore.resource.Resource;
@@ -202,7 +204,17 @@ public abstract class RegistryReader
           protected Set<URI> uris = new HashSet<URI>();
 
           @Override
-          protected Resource delegatedGetResource(URI uri, boolean loadOnDemand)
+		  public synchronized Resource getResource(URI uri, boolean loadOnDemand) {
+			return super.getResource(uri, loadOnDemand);
+		  }
+
+		  @Override
+		  public synchronized Resource createResource(URI uri, String contentType) {
+			return super.createResource(uri, contentType);
+		  }
+
+		  @Override
+          protected synchronized Resource delegatedGetResource(URI uri, boolean loadOnDemand)
           {
             try
             {
@@ -244,7 +256,11 @@ public abstract class RegistryReader
             }
             else
             {
-              return (EPackage) EcoreUtil.getObjectByType(resourceSet.getResource(locationURI, true).getContents(), EcorePackage.Literals.EPACKAGE);
+              Resource r = resourceSet.getResource(locationURI, true);
+              if (r != null)
+            	  	return (EPackage) EcoreUtil.getObjectByType(r.getContents(), EcorePackage.Literals.EPACKAGE);
+              else
+            	  	throw new RuntimeException("No EPackage found at: " + locationURI);
             }
           }
           else
diff --git a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/resource/impl/ResourceSetImpl.java b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/resource/impl/ResourceSetImpl.java
index 6f896e8..7c76108 100644
--- a/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/resource/impl/ResourceSetImpl.java
+++ b/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/resource/impl/ResourceSetImpl.java
@@ -432,7 +432,9 @@ public class ResourceSetImpl extends NotifierImpl implements ResourceSet
     if (resourceFactory != null)
     {
       Resource result = resourceFactory.createResource(uri);
-      getResources().add(result);
+      if (result != null) {
+    	  	getResources().add(result);
+      }
       return result;
     }
     else


- Nicolas.
Re: Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)? [message #1520647 is a reply to message #1519740] Sun, 21 December 2014 09:49 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33113
Registered: July 2009
Senior Member
Nicolas,

Comments below.

On 20/12/2014 10:26 PM, Nicolas Rouquette wrote:
> There seem to be several problems involved.
>
> 1) no resource factory registered for *.xcore
>
> https://bugs.eclipse.org/bugs/show_bug.cgi?id=453329
>
> Jonas' last comment is definitely relevant since both QVTO's Metamodel
> Browser view and QVTO's Compiler do browse the EPackage registry for
> metamodels.
That may be, but shouldn't those metamodels should be development time
models?
>
> Quote:
>> Added Ed for information, because this problem might affect other
>> frameworks too, which browse the package registry.
>
>
> How do I tell if this bug affects me?
I guess you'd see the stack trace from that bugzilla.
>
> The ResourceSet involved -- i.e.:
> org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.resourceSet
> -- does not have any resource factory.
Keeing in mind that the local resource set's resource factory delegates
to the global one...
> I don't understand how having or not a resource factory for XCore.lang
> per se would have such a particular impact on a small fraction of
> completely unrelated metamodels!
If something loads all models in the registry aggressively, then it's
sort of irrelevant whether it's related to what you're doing on or not.
>
> This bug may be a factor but it seems that it's not enough.
> There must be something else involved.
>
> 2) vulnerability to NPE
>
> Shouldn't Eclipse initialize cleanly without any NPEs?
Of course.
>
> Since ResourceSet.getResource() may return null, the code in
> org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.getEPackage()
> will trip an NPE in precisely such case:
Which we could ignore, but it is indicative of an underlying problem
which is best not to ignore.
>
>
> return (EPackage)
> EcoreUtil.getObjectByType(resourceSet.getResource(locationURI,
> true).getContents(), EcorePackage.Literals.EPACKAGE);
>
>
> I really would like to see this fixed -- it's annoying to get these
> NPEs when launching Eclispe under the debugger.
>
> Is this enough to cause the problems? Again, it may be a symptom but
> it does not seem to be sufficient by itself.
Generally bugs get fixed when they are reported with a suitable test
case. (And I'm not generally happy with bugs whose reproduction
including "install the following large stack of technology").
>
> 3) concurrency problems.
>
>>> The problem is really due to concurrent calls to
>>> ResourceSet.add(Resource) because the default implementation (i.e.
>>> ResourceSetImpl) is not thread-safe for concurrent modification.
>>> I managed to work around the problem by synchronizing calls to
>>> ResourceSetImpl::add(Resource):
>> No, resource sets aren't designed or intended to be thread safe and
>> adding synchronization will be a source of deadlock. Better to look
>> at something like
>> org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.getEPackage()
>> and make sure that it hold a lock on the resource set rather than
>> start sprinkling synchronization into all resource set implementations.
>
> I don't understand.
>
> If resource sets are not designed nor intended to be thread safe, then
> doesn't this imply that there should be at most 1 thread modifying a
> given resource set at any time?
Yes.
> If it does, then why would adding synchronization using the resource
> set itself be a source of deadlock?
Because the method you added it to calls what else, which calls what
else, which does what other kinds of locking and synchronization?
Goodness only knows, but what you're proposing is like going to
ArrayList and modifying the add method to be synchronized; it's just not
the intent of the ArrayList implement to be thread safe in this way.
>
> In examining the code involved in the stack trace, I noticed that
> there is in fact synchronization in a different method:
>
> org.eclipse.xtext.xbase.resource.BatchLinkableResource.getContents():
>
>
> public EList<EObject> getContents() {
> synchronized (getLock()) {
> if (isLoaded && !isLoading && !isInitializing &&
> !isUpdating && !fullyInitialized) {
> try {
> eSetDeliver(false);
> installDerivedState(false);
> } finally {
> eSetDeliver(true);
> }
> }
> return doGetContents();
> }
> }
In an Xtext resource; apparently you do have Xcore's resource factory
registered.
>
>
> In this case -- i.e., the resource set is:
> org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.resourceSet
> Since it isn't an ISynchronizable, getLock() returns 'this' -- i.e.
> the resource itself.
>
>
> /**
> * Returns the lock of the owning {@link ResourceSet}, if it
> exposes such a lock.
> * Otherwise this resource itself is used as the lock context.
> */
> /* @NonNull */
> public Object getLock() {
> ResourceSet resourceSet = getResourceSet();
> if (resourceSet instanceof ISynchronizable<?>) {
> return ((ISynchronizable<?>) resourceSet).getLock();
> }
> return this;
> }
>
>
> What happens then?
>
> Well, we can have multiple threads that will concurrently attempt to
> initialize XCore's metamodels but with *different* Resource objects --
> i.e. different Resources loaded from
> uri='platform:/plugin/org.eclipse.emf.ecore.xcore.lib/model/XcoreLang.xcore'
>
> Here are some examples:
>
>
> Daemon Thread
> [org.eclipse.m2m.internal.qvt.oml.editor.ui.QvtReconciler] (Suspended)
> owns: XcoreResource (id=172)
> XcoreResource(BatchLinkableResource).getContents() line: 130
> XcoreResource(XtextResource).updateInternalState(IParseResult)
> line: 253
> XcoreResource(DerivedStateAwareResource).updateInternalState(IParseResult)
> line: 101
> XcoreResource(XtextResource).updateInternalState(IParseResult,
> IParseResult) line: 248
> XcoreResource(DerivedStateAwareResource).updateInternalState(IParseResult,
> IParseResult) line: 93
> XcoreResource(XtextResource).doLoad(InputStream, Map<?,?>) line: 161
> XcoreResource(LazyLinkingResource).doLoad(InputStream, Map<?,?>)
> line: 100
> XcoreResource(ResourceImpl).load(InputStream, Map<?,?>) line: 1518
> XcoreResource(ResourceImpl).load(Map<?,?>) line: 1297
> RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).demandLoad(Resource)
> line: 259
> RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).demandLoadHelper(Resource)
> line: 274
> RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).getResource(URI,
> boolean) line: 406
> RegistryReader$EPackageDescriptor$Dynamic.getEPackage() line: 249
> EmfMetamodelDesc.getModel() line: 61
> EmfMetamodelDesc.getLoadStatus() line: 91
> MetamodelRegistry.toEPackageRegistry() line: 95
> CompilerUtils.getEPackageRegistry(URI, IMetamodelRegistryProvider)
> line: 107
> QVTOCompiler.getEPackageRegistry(URI) line: 529
> QVTOCompiler.parse(UnitProxy, QvtCompilerOptions) line: 233
> QVTOCompiler.doCompile(UnitProxy, QvtCompilerOptions, Monitor)
> line: 369
> QVTOCompiler.compileSingleFile(UnitProxy, QvtCompilerOptions,
> Monitor) line: 326
> QVTOCompiler.compile(UnitProxy[], QvtCompilerOptions, Monitor)
> line: 211
> QVTOCompiler.compile(UnitProxy, QvtCompilerOptions, Monitor) line:
> 224
> QvtCompilerFacade.compile(ITextEditor, IDocument,
> QvtCompilerOptions, IProgressMonitor) line: 77
> QvtReconcilingStrategy.getCompilationResult(boolean) line: 90
> QvtReconcilingStrategy.reconcileInternal() line: 74
> QvtReconcilingStrategy.initialReconcile() line: 62
> QvtReconciler(MonoReconciler).initialProcess() line: 105
> AbstractReconciler$BackgroundThread.run() line: 173
>
>
> and:
>
>
> Daemon Thread
> [org.eclipse.m2m.internal.qvt.oml.editor.ui.QvtReconciler] (Suspended)
> owns: XcoreResource (id=186)
> XcoreResource(BatchLinkableResource).getContents() line: 130
> XcoreResource(XtextResource).updateInternalState(IParseResult)
> line: 253
> XcoreResource(DerivedStateAwareResource).updateInternalState(IParseResult)
> line: 101
> XcoreResource(XtextResource).updateInternalState(IParseResult,
> IParseResult) line: 248
> XcoreResource(DerivedStateAwareResource).updateInternalState(IParseResult,
> IParseResult) line: 93
> XcoreResource(XtextResource).doLoad(InputStream, Map<?,?>) line: 161
> XcoreResource(LazyLinkingResource).doLoad(InputStream, Map<?,?>)
> line: 100
> XcoreResource(ResourceImpl).load(InputStream, Map<?,?>) line: 1518
> XcoreResource(ResourceImpl).load(Map<?,?>) line: 1297
> RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).demandLoad(Resource)
> line: 259
> RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).demandLoadHelper(Resource)
> line: 274
> RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).getResource(URI,
> boolean) line: 406
> RegistryReader$EPackageDescriptor$Dynamic.getEPackage() line: 249
> EmfMetamodelDesc.getModel() line: 61
> EmfMetamodelDesc.getLoadStatus() line: 91
> MetamodelRegistry.toEPackageRegistry() line: 95
> CompilerUtils.getEPackageRegistry(URI, IMetamodelRegistryProvider)
> line: 107
> QVTOCompiler.getEPackageRegistry(URI) line: 529
> QVTOCompiler.parse(UnitProxy, QvtCompilerOptions) line: 233
> QVTOCompiler.doCompile(UnitProxy, QvtCompilerOptions, Monitor)
> line: 369
> QVTOCompiler.compileSingleFile(UnitProxy, QvtCompilerOptions,
> Monitor) line: 326
> QVTOCompiler.compile(UnitProxy[], QvtCompilerOptions, Monitor)
> line: 211
> QVTOCompiler.compile(UnitProxy, QvtCompilerOptions, Monitor) line:
> 224
> QvtCompilerFacade.compile(ITextEditor, IDocument,
> QvtCompilerOptions, IProgressMonitor) line: 77
> QvtReconcilingStrategy.getCompilationResult(boolean) line: 90
> QvtReconcilingStrategy.reconcileInternal() line: 74
> QvtReconcilingStrategy.initialReconcile() line: 62
> QvtReconciler(MonoReconciler).initialProcess() line: 105
> AbstractReconciler$BackgroundThread.run() line: 173
>
>
> and:
>
>
> Daemon Thread
> [org.eclipse.m2m.internal.qvt.oml.editor.ui.QvtReconciler] (Suspended)
> owns: XcoreResource (id=190)
> XcoreResource(BatchLinkableResource).getContents() line: 130
> XcoreResource(XtextResource).updateInternalState(IParseResult)
> line: 253
> XcoreResource(DerivedStateAwareResource).updateInternalState(IParseResult)
> line: 101
> XcoreResource(XtextResource).updateInternalState(IParseResult,
> IParseResult) line: 248
> XcoreResource(DerivedStateAwareResource).updateInternalState(IParseResult,
> IParseResult) line: 93
> XcoreResource(XtextResource).doLoad(InputStream, Map<?,?>) line: 161
> XcoreResource(LazyLinkingResource).doLoad(InputStream, Map<?,?>)
> line: 100
> XcoreResource(ResourceImpl).load(InputStream, Map<?,?>) line: 1518
> XcoreResource(ResourceImpl).load(Map<?,?>) line: 1297
> RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).demandLoad(Resource)
> line: 259
> RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).demandLoadHelper(Resource)
> line: 274
> RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).getResource(URI,
> boolean) line: 406
> RegistryReader$EPackageDescriptor$Dynamic.getEPackage() line: 249
> EmfMetamodelDesc.getModel() line: 61
> EmfMetamodelDesc.getLoadStatus() line: 91
> MetamodelRegistry.toEPackageRegistry() line: 95
> CompilerUtils.getEPackageRegistry(URI, IMetamodelRegistryProvider)
> line: 107
> QVTOCompiler.getEPackageRegistry(URI) line: 529
> QVTOCompiler.parse(UnitProxy, QvtCompilerOptions) line: 233
> QVTOCompiler.doCompile(UnitProxy, QvtCompilerOptions, Monitor)
> line: 369
> QVTOCompiler.compileSingleFile(UnitProxy, QvtCompilerOptions,
> Monitor) line: 326
> QVTOCompiler.compile(UnitProxy[], QvtCompilerOptions, Monitor)
> line: 211
> QVTOCompiler.compile(UnitProxy, QvtCompilerOptions, Monitor) line:
> 224
> QvtCompilerFacade.compile(ITextEditor, IDocument,
> QvtCompilerOptions, IProgressMonitor) line: 77
> QvtReconcilingStrategy.getCompilationResult(boolean) line: 90
> QvtReconcilingStrategy.reconcileInternal() line: 74
> QvtReconcilingStrategy.initialReconcile() line: 62
> QvtReconciler(MonoReconciler).initialProcess() line: 105
> AbstractReconciler$BackgroundThread.run() line: 173
>
>
> and:
>
>
> Thread [main] (Suspended)
> owns: XcoreResource (id=126)
> XcoreResource(BatchLinkableResource).getContents() line: 130
> XcoreResource(XtextResource).updateInternalState(IParseResult)
> line: 253
> XcoreResource(DerivedStateAwareResource).updateInternalState(IParseResult)
> line: 101
> XcoreResource(XtextResource).updateInternalState(IParseResult,
> IParseResult) line: 248
> XcoreResource(DerivedStateAwareResource).updateInternalState(IParseResult,
> IParseResult) line: 93
> XcoreResource(XtextResource).doLoad(InputStream, Map<?,?>) line: 161
> XcoreResource(LazyLinkingResource).doLoad(InputStream, Map<?,?>)
> line: 100
> XcoreResource(ResourceImpl).load(InputStream, Map<?,?>) line: 1518
> XcoreResource(ResourceImpl).load(Map<?,?>) line: 1297
> RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).demandLoad(Resource)
> line: 259
> RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).demandLoadHelper(Resource)
> line: 274
> RegistryReader$EPackageDescriptor$Dynamic$1(ResourceSetImpl).getResource(URI,
> boolean) line: 406
> RegistryReader$EPackageDescriptor$Dynamic.getEPackage() line: 249
> EmfMetamodelDesc.getModel() line: 61
> MetamodelBrowserView$3(MetamodelBrowser).doCreateInput() line: 502
> MetamodelBrowser$5.run() line: 473
> BusyIndicator.showWhile(Display, Runnable) line: 70
> MetamodelBrowserView$3(MetamodelBrowser).createInput() line: 471
> MetamodelBrowserView$3(MetamodelBrowser).<init>(Composite, int)
> line: 168
> MetamodelBrowserView$3(MetamodelBrowser).<init>(Composite) line: 145
> MetamodelBrowserView$3.<init>(MetamodelBrowserView, Composite)
> line: 108
> MetamodelBrowserView.createPartControl(Composite) line: 108
> CompatibilityView(CompatibilityPart).createPartControl(IWorkbenchPart,
> Composite) line: 141
> CompatibilityView.createPartControl(IWorkbenchPart, Composite)
> line: 155
> CompatibilityView(CompatibilityPart).create() line: 327
> NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line:
> not available [native method]
> NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62
> DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
> Method.invoke(Object, Object...) line: 483
> MethodRequestor.execute() line: 55
> InjectorImpl.processAnnotated(Class<Annotation>, Object, Class<?>,
> PrimaryObjectSupplier, PrimaryObjectSupplier, ArrayList<Class<?>>)
> line: 888
> InjectorImpl.processAnnotated(Class<Annotation>, Object, Class<?>,
> PrimaryObjectSupplier, PrimaryObjectSupplier, ArrayList<Class<?>>)
> line: 869
> InjectorImpl.inject(Object, PrimaryObjectSupplier,
> PrimaryObjectSupplier) line: 120
> InjectorImpl.internalMake(Class<?>, PrimaryObjectSupplier,
> PrimaryObjectSupplier) line: 337
> InjectorImpl.make(Class<T>, PrimaryObjectSupplier) line: 258
> ContextInjectionFactory.make(Class<T>, IEclipseContext) line: 162
> ReflectionContributionFactory.createFromBundle(Bundle,
> IEclipseContext, IEclipseContext, URI) line: 104
> ReflectionContributionFactory.doCreate(String, IEclipseContext,
> IEclipseContext) line: 73
> ReflectionContributionFactory.create(String, IEclipseContext)
> line: 55
> ContributedPartRenderer.createWidget(MUIElement, Object) line: 127
> PartRenderingEngine.createWidget(MUIElement, Object) line: 983
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 662
> PartRenderingEngine$6.run() line: 547
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement, Object, IEclipseContext)
> line: 531
> ElementReferenceRenderer.createWidget(MUIElement, Object) line: 69
> PartRenderingEngine.createWidget(MUIElement, Object) line: 983
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 662
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> StackRenderer.showTab(MUIElement) line: 1250
> StackRenderer(LazyStackRenderer).postProcess(MUIElement) line: 100
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 678
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>)
> line: 68
> SashRenderer.processContents(MElementContainer<MUIElement>) line: 185
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>)
> line: 68
> SashRenderer.processContents(MElementContainer<MUIElement>) line: 185
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>)
> line: 68
> SashRenderer.processContents(MElementContainer<MUIElement>) line: 185
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> PerspectiveRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>)
> line: 68
> PerspectiveRenderer.processContents(MElementContainer<MUIElement>)
> line: 49
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> PerspectiveStackRenderer.showTab(MUIElement) line: 103
> PerspectiveStackRenderer(LazyStackRenderer).postProcess(MUIElement) line:
> 100
> PerspectiveStackRenderer.postProcess(MUIElement) line: 77
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 678
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> SashRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>)
> line: 68
> SashRenderer.processContents(MElementContainer<MUIElement>) line: 185
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> WBWRenderer(SWTPartRenderer).processContents(MElementContainer<MUIElement>)
> line: 68
> WBWRenderer.processContents(MElementContainer<MUIElement>) line: 664
> PartRenderingEngine.safeCreateGui(MUIElement, Object,
> IEclipseContext) line: 674
> PartRenderingEngine.safeCreateGui(MUIElement) line: 766
> PartRenderingEngine.access$2(PartRenderingEngine, MUIElement)
> line: 737
> PartRenderingEngine$7.run() line: 731
> SafeRunner.run(ISafeRunnable) line: 42
> PartRenderingEngine.createGui(MUIElement) line: 715
> PartRenderingEngine$9.run() line: 1078
> Realm.runWithDefault(Realm, Runnable) line: 332
> PartRenderingEngine.run(MApplicationElement, IEclipseContext)
> line: 1032
> E4Workbench.createAndRunUI(MApplicationElement) line: 148
> Workbench$5.run() line: 636
> Realm.runWithDefault(Realm, Runnable) line: 332
> Workbench.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 579
> PlatformUI.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 150
> IDEApplication.start(IApplicationContext) line: 135
> EclipseAppHandle.run(Object) line: 196
> EclipseAppLauncher.runApplication(Object) line: 134
> EclipseAppLauncher.start(Object) line: 104
> EclipseStarter.run(Object) line: 380
> EclipseStarter.run(String[], Runnable) line: 235
> NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line:
> not available [native method]
> NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62
> DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
> Method.invoke(Object, Object...) line: 483
> Main.invokeFramework(String[], URL[]) line: 648
> Main.basicRun(String[]) line: 603
> Main.run(String[]) line: 1465
> Main.main(String[]) line: 1438
>
>
> Even though I stopped all of these threads, the RegistryReader's
> ResourceSet is already compromised:
>
> resourceSet
> org.eclipse.emf.ecore.plugin.RegistryReader$EPackageDescriptor$Dynamic$1
> (id=128)
>
> org.eclipse.emf.ecore.plugin.RegistryReader$EPackageDescriptor$Dynamic$1@50ad5eb8
> resources=[mailto:org.eclipse.emf.ecore.xcore.resource.XcoreResource@e11cb3b
> uri='platform:/plugin/org.eclipse.emf.ecore.xcore.lib/model/XcoreLang.xcore',
> null, null,
> mailto:org.eclipse.emf.ecore.xcore.resource.XcoreResource@6e716c17
> uri='platform:/plugin/org.eclipse.emf.ecore.xcore.lib/model/XcoreLang.xcore']
>
>
> There are already 2 null values and XcoreLang appears twice already!
Yes, that can't be good.
>
> Even though it may not be the best way to fix the problem, it's
> interesting that adding a synchronization on
> ResourceSetImpl.add(Resource) suffices to avoid this problem (it could
> cause others as Ed M pointed out).
Better to fix the problem specific to the use of the one resource set by
the dynamic package registry.
>
> - Nicolas.
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)? [message #1521754 is a reply to message #1520647] Mon, 22 December 2014 00:54 Go to previous messageGo to next message
Nicolas Rouquette is currently offline Nicolas RouquetteFriend
Messages: 157
Registered: July 2009
Senior Member
Ed,

Quote:

> If it does, then why would adding synchronization using the resource
> set itself be a source of deadlock?
Because the method you added it to calls what else, which calls what
else, which does what other kinds of locking and synchronization?
Goodness only knows, but what you're proposing is like going to
ArrayList and modifying the add method to be synchronized; it's just not
the intent of the ArrayList implement to be thread safe in this way.
...
> Even though it may not be the best way to fix the problem, it's
> interesting that adding a synchronization on
> ResourceSetImpl.add(Resource) suffices to avoid this problem (it could
> cause others as Ed M pointed out).
Better to fix the problem specific to the use of the one resource set by
the dynamic package registry.


Does the fix below correspond to your suggestion to fix the specific problem in the dynamic package registry?

https://www.eclipse.org/forums/index.php?t=msg&th=899781&goto=1519861&#msg_1519861

- Nicolas.
Re: Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)? [message #1522402 is a reply to message #1521754] Mon, 22 December 2014 09:36 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33113
Registered: July 2009
Senior Member
Nicolas,

Comments below.

On 22/12/2014 1:54 AM, Nicolas Rouquette wrote:
> Ed,
>
> Quote:
>> > If it does, then why would adding synchronization using the
>> resource > set itself be a source of deadlock?
>> Because the method you added it to calls what else, which calls what
>> else, which does what other kinds of locking and synchronization?
>> Goodness only knows, but what you're proposing is like going to
>> ArrayList and modifying the add method to be synchronized; it's just
>> not the intent of the ArrayList implement to be thread safe in this way.
>> ...
>> > Even though it may not be the best way to fix the problem, it's >
>> interesting that adding a synchronization on >
>> ResourceSetImpl.add(Resource) suffices to avoid this problem (it
>> could > cause others as Ed M pointed out).
>> Better to fix the problem specific to the use of the one resource set
>> by the dynamic package registry.
>
>
> Does the fix below correspond to your suggestion to fix the specific
> problem in the dynamic package registry?
No, that logic focuses on guarding the creation of a new resource, but
one most also consider the logic that simply finds a resource already in
the resource set while a second thread is creating a resource. Perhaps
the second thread will need to grow the underlying list while the first
thread is iterating over it. All access, both read and write, needs
guarding. That could be done by synchronizing on the resource set
rather than adding synchronize to specialized methods of the resource set.

Also, I see no need to check that a resource factory actually returns a
resource given that the list of resources itself is guarded to prevent
null from being added.
>
> https://www.eclipse.org/forums/index.php?t=msg&th=899781&goto=1519861&#msg_1519861
>
>
> - Nicolas.


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)? [message #1522949 is a reply to message #1522402] Mon, 22 December 2014 16:44 Go to previous messageGo to next message
Nicolas Rouquette is currently offline Nicolas RouquetteFriend
Messages: 40
Registered: December 2014
Member
Ed,

Ed Merks wrote on Mon, 22 December 2014 09:36

> Does the fix below correspond to your suggestion to fix the specific
> problem in the dynamic package registry?
No, that logic focuses on guarding the creation of a new resource, but
one most also consider the logic that simply finds a resource already in
the resource set while a second thread is creating a resource. Perhaps
the second thread will need to grow the underlying list while the first
thread is iterating over it. All access, both read and write, needs
guarding. That could be done by synchronizing on the resource set
rather than adding synchronize to specialized methods of the resource set.


Is that enough?

Synchronizing access to the ResourceSet does not guarantee synchronized access to the list of Resources.

Consider a typical use of the API:

ResourceSet rs = ...;
rs.getResources().add(...);

Synchronizing access to rs will only serialize the calls to rs.getResources() but it won't guarantee serialization of the additions.

- Nicolas.

Re: Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)? [message #1523013 is a reply to message #1522402] Mon, 22 December 2014 17:34 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi Ed

On 22/12/2014 09:36, Ed Merks wrote:
> All access, both read and write, needs
> guarding. That could be done by synchronizing on the resource set
> rather than adding synchronize to specialized methods of the resource set.

https://bugs.eclipse.org/bugs/show_bug.cgi?id=455980

raised to discuss a policy.

Regards

Ed Willink
Re: Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)? [message #1524195 is a reply to message #1522949] Tue, 23 December 2014 09:25 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33113
Registered: July 2009
Senior Member
Nicolas,

Comments below.

On 22/12/2014 6:15 PM, Nicolas Rouquette wrote:
> Ed,
>
> Ed Merks wrote on Mon, 22 December 2014 09:36
>> > Does the fix below correspond to your suggestion to fix the
>> specific > problem in the dynamic package registry?
>> No, that logic focuses on guarding the creation of a new resource,
>> but one most also consider the logic that simply finds a resource
>> already in the resource set while a second thread is creating a
>> resource. Perhaps the second thread will need to grow the underlying
>> list while the first thread is iterating over it. All access, both
>> read and write, needs guarding. That could be done by synchronizing
>> on the resource set rather than adding synchronize to specialized
>> methods of the resource set.
>
>
> Is that enough?
>
> Synchronizing access to the ResourceSet does not guarantee
> synchronized access to the list of Resources.
That's true, but this resource set
(org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.resourceSet)
is intended only for the purpose of loading/finding registered dynamic
packages so the only place its used is in
org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.getEPackage()
so it's sufficient that the use within that method be guarded. The
simplest way to do that is to make getEPackage itself synchronized, but
likely we can do something more fine-grained. We we don't need is to
try to make the whole resource set thread safe, because that's a losing
battle.
>
> Consider a typical use of the API:
>
> ResourceSet rs = ...;
> rs.getResources().add(...);
>
> Synchronizing access to rs will only serialize the calls to
> rs.getResources() but it won't guarantee serialization of the additions.
Exactly, and nothing will help with iteration, which is why Vector fell
out of favor and ArrayList is used instead.
>
> - Nicolas.
>
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)? [message #1524467 is a reply to message #1524195] Tue, 23 December 2014 13:00 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

On 23/12/2014 09:25, Ed Merks wrote:
>
>>
>> Consider a typical use of the API:
>>
>> ResourceSet rs = ...;
>> rs.getResources().add(...);
>>

My suggestion is that you must

ResourceSet rs = ...
synchronized (rs) {
rs.getResources().add(...)
}

so that by acquiring arbitrated exclusive access to the ResourceSet you
acquire implied exclusive access to all its content too.

The ResourceSet mutex just acts as a token passed from thread to thread
identifying which thread is THE EMF thread that may may arbitrary changes.

Arbitrating access ONLY at the coarsest grain provides a reasonable
opportunity to avoid deadlocks. Framework code must NOT synchronize
since synchronization is an application responsibility.

(To support multi-readers in a post-resolveAll world, internal caches
should synchronize on their caches to avoid concurrent lazy cacheing.)

Regards

Ed Willink
Re: Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)? [message #1526947 is a reply to message #1524467] Wed, 24 December 2014 22:37 Go to previous messageGo to next message
Nicolas Rouquette is currently offline Nicolas RouquetteFriend
Messages: 40
Registered: December 2014
Member
Ed Willink wrote on Tue, 23 December 2014 13:00

On 23/12/2014 09:25, Ed Merks wrote:
>
>>
>> Consider a typical use of the API:
>>
>> ResourceSet rs = ...;
>> rs.getResources().add(...);
>>

My suggestion is that you must

ResourceSet rs = ...
synchronized (rs) {
rs.getResources().add(...)
}

so that by acquiring arbitrated exclusive access to the ResourceSet you
acquire implied exclusive access to all its content too.


I doubt that this suggestion is sufficient.

Consider ResourceSetImpl.createResource:

public Resource createResource(URI uri, String contentType)
  {
    Resource.Factory resourceFactory = getResourceFactoryRegistry().getFactory(uri, contentType);
    if (resourceFactory != null)
    {
      Resource result = resourceFactory.createResource(uri);
      if (result != null) {
    	  	getResources().add(result);
      }
      return result;
    }
    else
    {
      return null;
    }
  }


By your suggestion, this would have to be synchronized.

Quote:

The ResourceSet mutex just acts as a token passed from thread to thread
identifying which thread is THE EMF thread that may may arbitrary changes.

Arbitrating access ONLY at the coarsest grain provides a reasonable
opportunity to avoid deadlocks. Framework code must NOT synchronize
since synchronization is an application responsibility.


But you exclude framework code; which means that callers of ResourceSet.createResource() would also have to be synchronized outside of framework code.

The problem here is that the ResourceSet API exposes the resources it manages as a mutable list.
Yet, it's clear now that we shouldn't have concurrent modification of that list.

I think that there are roughly 3 different strategies to address this problem:

Strategy1: keep the ResourceSet API as-is but add policies to ensure serialization of modification of a ResourceSet and of its managed Resources

It is difficult to identify how many policies are needed because the API "leaks" mutable state -- e.g., ResourceSet.getResources() -- so it expands the scope of objects we have to directly and indirectly synchronize access to.

Your suggestion is an example of such a policy but it is incomplete.
As Ed M observed, org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.getEPackage() isn't thread safe. This means its access would have to be covered somehow in a synchronization policy.

Even if someone could come up with a reasonable list of policies; this strategy would be particularly expensive to adopt
since it would require refactoring lots of EMF-based applications.

Strategy2: fix the ResourceSet API to prevent leaking mutable state

Currently, ResourceSet.getResources() returns a mutable list -- i.e., it leaks mutable state.
In this strategy, this API would be changed to return an immutable list instead and there
would be a new API to add a Resource to a ResourceSet.

This strategy would require some refactoring of EMF-based applications but not as much as the previous strategy.

Strategy3: manage the EMF EPackage registry in dedicated thread

This is a hybrid of the 2 with the difference that instead of imposing synchronization code on EMF-based applications,
there would be a dedicated EMF thread per each EMF EPackage registry and all of the related objects it involves
(e.g. the RegistryReader dynamic ResourceSet). For EMF client applications, the EMF EPackage registry API would look like it does today (except for refactoring API methods that leak state into a pair of a query/update API methods per strategy 2). These API methods would queue requests to the EMF EPackage registry thread which would ensure that all operations on the EPackage registry & related objects would be serialized. Some APIs would have to be refactored to include callback operations -- e.g. to enable loading EMF EPackages on the client's class loader instead of the the EMF EPackage registry thread's class loader.

What do you think?

- Nicolas.
Re: Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)? [message #1529376 is a reply to message #1526947] Fri, 26 December 2014 08:00 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi Nicolas

I am not suggesting that synchronizing the ResourceSet gives arbitrated
solution to all EMF accesses. A total solution would require fine
grained mutexes and be completely incompatible with the EMF design.

I am suggesting an agreed policy whereby each thread in a multithreaded
EMF application must acquire the ResourceSet mutex before doing any EMF
access on the ResourceSet. The ResourceSet mutex can be fully arbitrated.

Your example of ResourceSetImpl.createResource, like numerous EMF
routines, is not threadsafe. The solution is not to recode it, but to
follow my suggested policy. The thread in which
ResourceSetImpl.createResource is called is required to acquire the
ResourceSet mutex before calling ResourceSetImpl.createResource. The
solution is therefore pushed back to the original caller and so is a
'simple' application code adherence requiring no change at all to the
EMF framework.

Regards

Ed Willink

On 24/12/2014 22:37, Nicolas Rouquette wrote:
> Ed Willink wrote on Tue, 23 December 2014 13:00
>> On 23/12/2014 09:25, Ed Merks wrote:
>> >
>> >>
>> >> Consider a typical use of the API:
>> >>
>> >> ResourceSet rs = ...;
>> >> rs.getResources().add(...);
>> >>
>>
>> My suggestion is that you must
>>
>> ResourceSet rs = ...
>> synchronized (rs) {
>> rs.getResources().add(...)
>> }
>>
>> so that by acquiring arbitrated exclusive access to the ResourceSet
>> you acquire implied exclusive access to all its content too.
>
>
> I doubt that this suggestion is sufficient.
>
> Consider ResourceSetImpl.createResource:
>
>
> public Resource createResource(URI uri, String contentType)
> {
> Resource.Factory resourceFactory =
> getResourceFactoryRegistry().getFactory(uri, contentType);
> if (resourceFactory != null)
> {
> Resource result = resourceFactory.createResource(uri);
> if (result != null) {
> getResources().add(result);
> }
> return result;
> }
> else
> {
> return null;
> }
> }
>
>
> By your suggestion, this would have to be synchronized.
>
> Quote:
>> The ResourceSet mutex just acts as a token passed from thread to
>> thread identifying which thread is THE EMF thread that may may
>> arbitrary changes.
>>
>> Arbitrating access ONLY at the coarsest grain provides a reasonable
>> opportunity to avoid deadlocks. Framework code must NOT synchronize
>> since synchronization is an application responsibility.
>
>
> But you exclude framework code; which means that callers of
> ResourceSet.createResource() would also have to be synchronized outside
> of framework code.
>
> The problem here is that the ResourceSet API exposes the resources it
> manages as a mutable list. Yet, it's clear now that we shouldn't have
> concurrent modification of that list.
>
> I think that there are roughly 3 different strategies to address this
> problem:
>
> Strategy1: keep the ResourceSet API as-is but add policies to ensure
> serialization of modification of a ResourceSet and of its managed Resources
>
> It is difficult to identify how many policies are needed because the API
> "leaks" mutable state -- e.g., ResourceSet.getResources() -- so it
> expands the scope of objects we have to directly and indirectly
> synchronize access to.
>
> Your suggestion is an example of such a policy but it is incomplete.
> As Ed M observed,
> org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.getEPackage()
> isn't thread safe. This means its access would have to be covered
> somehow in a synchronization policy.
>
> Even if someone could come up with a reasonable list of policies; this
> strategy would be particularly expensive to adopt
> since it would require refactoring lots of EMF-based applications.
>
> Strategy2: fix the ResourceSet API to prevent leaking mutable state
>
> Currently, ResourceSet.getResources() returns a mutable list -- i.e., it
> leaks mutable state.
> In this strategy, this API would be changed to return an immutable list
> instead and there would be a new API to add a Resource to a ResourceSet.
>
> This strategy would require some refactoring of EMF-based applications
> but not as much as the previous strategy.
>
> Strategy3: manage the EMF EPackage registry in dedicated thread
>
> This is a hybrid of the 2 with the difference that instead of imposing
> synchronization code on EMF-based applications,
> there would be a dedicated EMF thread per each EMF EPackage registry and
> all of the related objects it involves
> (e.g. the RegistryReader dynamic ResourceSet). For EMF client
> applications, the EMF EPackage registry API would look like it does
> today (except for refactoring API methods that leak state into a pair of
> a query/update API methods per strategy 2). These API methods would
> queue requests to the EMF EPackage registry thread which would ensure
> that all operations on the EPackage registry & related objects would be
> serialized. Some APIs would have to be refactored to include callback
> operations -- e.g. to enable loading EMF EPackages on the client's class
> loader instead of the the EMF EPackage registry thread's class loader.
>
> What do you think?
>
> - Nicolas.
Re: Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)? [message #1529709 is a reply to message #1526947] Fri, 26 December 2014 12:39 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33113
Registered: July 2009
Senior Member
Nicolas,

As I said before, the specific problem you've pointed out is that
org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.getEPackage()
is not properly thread safe. That can be solved purely by making that
method thread safe, either by making the whole method synchronized, or
perhaps by doing something a little more fine-grained within the method
(e.g., synchronizing on the resource set before accessing it as Ed W has
suggested).

This discussion of trying to make ResourceSet itself thread safe is
simply a rat hole, and kind of pointless because I simply do no intend
to make any changes to synchronize a resource set's implementation. I
can pretty guarantee that any such approach will deadlock applications
that are already written with their own threading policy based on the
the assumption that there are no other locks involved.


On 24/12/2014 11:37 PM, Nicolas Rouquette wrote:
> Ed Willink wrote on Tue, 23 December 2014 13:00
>> On 23/12/2014 09:25, Ed Merks wrote:
>> >
>> >>
>> >> Consider a typical use of the API:
>> >>
>> >> ResourceSet rs = ...;
>> >> rs.getResources().add(...);
>> >>
>>
>> My suggestion is that you must
>>
>> ResourceSet rs = ...
>> synchronized (rs) {
>> rs.getResources().add(...)
>> }
>>
>> so that by acquiring arbitrated exclusive access to the ResourceSet
>> you acquire implied exclusive access to all its content too.
>
>
> I doubt that this suggestion is sufficient.
>
> Consider ResourceSetImpl.createResource:
>
>
> public Resource createResource(URI uri, String contentType)
> {
> Resource.Factory resourceFactory =
> getResourceFactoryRegistry().getFactory(uri, contentType);
> if (resourceFactory != null)
> {
> Resource result = resourceFactory.createResource(uri);
> if (result != null) {
> getResources().add(result);
> }
> return result;
> }
> else
> {
> return null;
> }
> }
>
>
> By your suggestion, this would have to be synchronized.
>
> Quote:
>> The ResourceSet mutex just acts as a token passed from thread to
>> thread identifying which thread is THE EMF thread that may may
>> arbitrary changes.
>>
>> Arbitrating access ONLY at the coarsest grain provides a reasonable
>> opportunity to avoid deadlocks. Framework code must NOT synchronize
>> since synchronization is an application responsibility.
>
>
> But you exclude framework code; which means that callers of
> ResourceSet.createResource() would also have to be synchronized
> outside of framework code.
>
> The problem here is that the ResourceSet API exposes the resources it
> manages as a mutable list. Yet, it's clear now that we shouldn't have
> concurrent modification of that list.
>
> I think that there are roughly 3 different strategies to address this
> problem:
>
> Strategy1: keep the ResourceSet API as-is but add policies to ensure
> serialization of modification of a ResourceSet and of its managed
> Resources
>
> It is difficult to identify how many policies are needed because the
> API "leaks" mutable state -- e.g., ResourceSet.getResources() -- so it
> expands the scope of objects we have to directly and indirectly
> synchronize access to.
>
> Your suggestion is an example of such a policy but it is incomplete.
> As Ed M observed,
> org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.getEPackage()
> isn't thread safe. This means its access would have to be covered
> somehow in a synchronization policy.
>
> Even if someone could come up with a reasonable list of policies; this
> strategy would be particularly expensive to adopt
> since it would require refactoring lots of EMF-based applications.
>
> Strategy2: fix the ResourceSet API to prevent leaking mutable state
>
> Currently, ResourceSet.getResources() returns a mutable list -- i.e.,
> it leaks mutable state.
> In this strategy, this API would be changed to return an immutable
> list instead and there would be a new API to add a Resource to a
> ResourceSet.
>
> This strategy would require some refactoring of EMF-based applications
> but not as much as the previous strategy.
>
> Strategy3: manage the EMF EPackage registry in dedicated thread
>
> This is a hybrid of the 2 with the difference that instead of imposing
> synchronization code on EMF-based applications,
> there would be a dedicated EMF thread per each EMF EPackage registry
> and all of the related objects it involves
> (e.g. the RegistryReader dynamic ResourceSet). For EMF client
> applications, the EMF EPackage registry API would look like it does
> today (except for refactoring API methods that leak state into a pair
> of a query/update API methods per strategy 2). These API methods would
> queue requests to the EMF EPackage registry thread which would ensure
> that all operations on the EPackage registry & related objects would
> be serialized. Some APIs would have to be refactored to include
> callback operations -- e.g. to enable loading EMF EPackages on the
> client's class loader instead of the the EMF EPackage registry
> thread's class loader.
>
> What do you think?
>
> - Nicolas.


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Is there a known vulnerability with concurrent calls to ResourceSetImpl.add(Resource)? [message #1530963 is a reply to message #1529709] Sat, 27 December 2014 05:44 Go to previous messageGo to next message
Nicolas Rouquette is currently offline Nicolas RouquetteFriend
Messages: 40
Registered: December 2014
Member
Ed Merks wrote on Fri, 26 December 2014 12:39
Nicolas,

As I said before, the specific problem you've pointed out is that
org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.getEPackage()
is not properly thread safe. That can be solved purely by making that
method thread safe, either by making the whole method synchronized, or
perhaps by doing something a little more fine-grained within the method
(e.g., synchronizing on the resource set before accessing it as Ed W has
suggested).


This definitely works, thanks!


Quote:

This discussion of trying to make ResourceSet itself thread safe is
simply a rat hole, and kind of pointless because I simply do no intend
to make any changes to synchronize a resource set's implementation. I
can pretty guarantee that any such approach will deadlock applications
that are already written with their own threading policy based on the
the assumption that there are no other locks involved.


Ok

Ed M's suggestion is definitely a big help but there's something complicated going on involving several factors:
- the "per thread" initialization of EPackageImpl until initialization is completed
- the order in which the global EPackage registry is initialized (e.g. the Eclipse QVTO MetamodelBrowser viewer)
- variations in the code idioms with which java-based EPackage implementations are initialized using static variables

From an end-user point of view, a visible manifestation of a snafu is that the Eclipse QVTO compiler fails to compile something like this:

"p.ownedElement->selectByKind(uml::PackageableElement)"

There's an error like this:

Cannot find operation (selectByKind(PackageableElement)) neither for the type (Set(Element)) nor for its element type (Element)


"selectByKind" is a peculiar operation. It's not the typical variety of java-based EOperation implementation.
See: org.eclipse.ocl.ecore.internal.OCLStandardLibraryImpl.stdlibPackage (it is a static variable)

There's no ecore extension point registering the OCL StandardLibrary package per se (unlike Ecore, OCL/Types, OCL/Expressions/... )

Any suggestions?

- Nicolas.

OCL/QVTo standard library (was Re: Is there a known vulnerability with concurrent calls to ResourceS [message #1531201 is a reply to message #1530963] Sat, 27 December 2014 08:56 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi Nicolas

Your observations on the selectByKind operation are absolutely nothing
to do with EMF.

selectByKind was introduced in OCL 2.4 and retrofitted to the Classic
Eclipse OCL and consequently 'inherited' by Eclipse QVTo.

https://bugs.eclipse.org/bugs/show_bug.cgi?id=439940 fixed a return type
error which might be your problem. Use OCL >= 5.0.2.

Your use of uml::PackageableElement is liable to vanish. The correct OMG
spelling is UML, and the UML2Ecore conversion now has support for
original names so that Java pragmatisms do not infect model level code.

It is possible that you are encountering another problem whereby the
QVTo extended standard library is inadequately extended.

I'm afraid that you are fighting a losing battle trying to ensure that
QVTo based on an unmodeled OCL standard library is sensible.

----

I promoted the new Pivot OCL from ".examples" yesterday in preparation
for release with Mars. It is extensible, has a model,

/org.eclipse.ocl.library/model/OCL-2.5.oclstdlib

an Xtext DSL and an extension point.

org.eclipse.ocl.pivot.standard_library

None of which helps you today.

While the Classic OCL has an oclstdlib.ecore, this is not really a model
since most of its declarations have six manual Java copies. The approach
adopts the co-Class idiom to accommodate EMOF's inability to define
operations for data types.

Even the Pivot OCL

/org.eclipse.ocl.library/model-gen/oclstdlib.ecore

is not a proper model since Ecore has no support for concepts such as
Iterations. The Ecore model exists solely to define the Ecore
referenceable type constructor primitives for OCL-defined nested
Collections and Tuples. The true model

/org.eclipse.ocl.library/model-gen/OCL-2.5.oclas

requires the UML-aligned Pivot concepts so that OCL references such as
OperationCallExp.referredOperation do not require proprietary XMI
serialization magic to make sort of sense. The Pivot model adds
LoopExp.referredIteration so that iterations too are resolved by
reference rather than an extra layer of name magic.

I hope that Mars+1 will see a Pivot-based QVTo with well-defined
*.qvtoas files and a direct-to-Java code generator.

Regards

Ed Willink

On 27/12/2014 05:44, Nicolas Rouquette wrote:
>
>
> From an end-user point of view, a visible manifestation of a snafu is
> that the Eclipse QVTO compiler fails to compile something like this:
>
> "p.ownedElement->selectByKind(uml::PackageableElement)"
>
> There's an error like this:
>
>
> Cannot find operation (selectByKind(PackageableElement)) neither for the
> type (Set(Element)) nor for its element type (Element)
>
>
> "selectByKind" is a peculiar operation. It's not the typical variety of
> java-based EOperation implementation.
> See:
> org.eclipse.ocl.ecore.internal.OCLStandardLibraryImpl.stdlibPackage (it
> is a static variable)
>
> There's no ecore extension point registering the OCL StandardLibrary
> package per se (unlike Ecore, OCL/Types, OCL/Expressions/... )
>
> Any suggestions?
>
> - Nicolas.
>
>
Re: OCL/QVTo standard library (was Re: Is there a known vulnerability with concurrent calls to Resou [message #1532435 is a reply to message #1531201] Sun, 28 December 2014 01:41 Go to previous messageGo to next message
Nicolas Rouquette is currently offline Nicolas RouquetteFriend
Messages: 40
Registered: December 2014
Member
Ed Willink wrote on Sat, 27 December 2014 08:56
Hi Nicolas

Your observations on the selectByKind operation are absolutely nothing
to do with EMF.


Some does -- see the registration of the OCL StandardLibrary package in the EMF EPackage registry.

Quote:

selectByKind was introduced in OCL 2.4 and retrofitted to the Classic
Eclipse OCL and consequently 'inherited' by Eclipse QVTo.

https://bugs.eclipse.org/bugs/show_bug.cgi?id=439940 fixed a return type
error which might be your problem. Use OCL >= 5.0.2.


Thanks; I wasn't worried about the fine details of QVTo but rather why the OCL StandardLibrary operations are sometimes unavailable.

Quote:

Your use of uml::PackageableElement is liable to vanish. The correct OMG
spelling is UML, and the UML2Ecore conversion now has support for
original names so that Java pragmatisms do not infect model level code.


The "uml" in "uml::PackageableElement" refers to the name of a QVTo modeltype.

Sometimes, QVTo developers use the old convention of a lowercase namespace prefix for a metamodel URI as the name of the QVTo model type declaration.

This is just a convention. I could use an arbitrary name for the model type, e.g.:

modeltype foo uses '....';

query bar( p : foo::PackageableElement ) : Collection( foo::PackageableElement ) {
  ....
}


Quote:

I promoted the new Pivot OCL from ".examples" yesterday in preparation
for release with Mars. It is extensible, has a model,

/org.eclipse.ocl.library/model/OCL-2.5.oclstdlib

an Xtext DSL and an extension point.

org.eclipse.ocl.pivot.standard_library

None of which helps you today.

While the Classic OCL has an oclstdlib.ecore, this is not really a model
since most of its declarations have six manual Java copies. The approach
adopts the co-Class idiom to accommodate EMOF's inability to define
operations for data types.

Even the Pivot OCL

/org.eclipse.ocl.library/model-gen/oclstdlib.ecore

is not a proper model since Ecore has no support for concepts such as
Iterations. The Ecore model exists solely to define the Ecore
referenceable type constructor primitives for OCL-defined nested
Collections and Tuples. The true model

/org.eclipse.ocl.library/model-gen/OCL-2.5.oclas

requires the UML-aligned Pivot concepts so that OCL references such as
OperationCallExp.referredOperation do not require proprietary XMI
serialization magic to make sort of sense. The Pivot model adds
LoopExp.referredIteration so that iterations too are resolved by
reference rather than an extra layer of name magic.

I hope that Mars+1 will see a Pivot-based QVTo with well-defined
*.qvtoas files and a direct-to-Java code generator.


Sounds nice & I look forward to it.

However, I hope you won't inherit whatever initialization-related weakness there is in the Luna code base of Eclipse OCL & QVTO that allows for the OCL StandardLibrary to be missing in the OCL / QVTo environment.

- Nicolas.
Re: OCL/QVTo standard library (was Re: Is there a known vulnerability with concurrent calls to Resou [message #1533944 is a reply to message #1532435] Sun, 28 December 2014 22:24 Go to previous messageGo to next message
Nicolas Rouquette is currently offline Nicolas RouquetteFriend
Messages: 40
Registered: December 2014
Member
Do we really need a unit test for submitting a patch to synchronize org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.getEPackage() ?

If yes, I need help writing a suitable unit test for emf.core.

- Nicolas.
Re: OCL/QVTo standard library (was Re: Is there a known vulnerability with concurrent calls to Resou [message #1534859 is a reply to message #1533944] Mon, 29 December 2014 10:42 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33113
Registered: July 2009
Senior Member
Nicolas,

No, just open a bugzilla and commit a review to Gerrit if you want
(using [<bugzilla-id] as the commit message prefix).


On 28/12/2014 11:24 PM, Nicolas Rouquette wrote:
> Do we really need a unit test for submitting a patch to synchronize
> org.eclipse.emf.ecore.plugin.RegistryReader.EPackageDescriptor.Dynamic.getEPackage()
> ?
>
> If yes, I need help writing a suitable unit test for emf.core.
>
> - Nicolas.


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: OCL/QVTo standard library (was Re: Is there a known vulnerability with concurrent calls to Resou [message #1535854 is a reply to message #1534859] Mon, 29 December 2014 23:50 Go to previous messageGo to next message
Nicolas Rouquette is currently offline Nicolas RouquetteFriend
Messages: 40
Registered: December 2014
Member
Ok, I opened 456299; I'll submit a patch to gerrit for review.

- Nicolas.
Re: OCL/QVTo standard library (was Re: Is there a known vulnerability with concurrent calls to Resou [message #1535909 is a reply to message #1535854] Tue, 30 December 2014 00:37 Go to previous messageGo to next message
Nicolas Rouquette is currently offline Nicolas RouquetteFriend
Messages: 40
Registered: December 2014
Member
This is strange.

I connected to the emf/org.eclipse.emf project with gerrit.
After I pushed to gerrit, Hudson CI started a job that failed:

https://hudson.eclipse.org/xtext/job/emf.gerrit/266/

I'm surprised that the hudson config is defined in xtext.
Is this normal?

The job itself failed:

https://hudson.eclipse.org/xtext/job/emf.gerrit/266/console

It seems that there's a configuration problem somewhere.

- Nicolas.
Re: OCL/QVTo standard library (was Re: Is there a known vulnerability with concurrent calls to Resou [message #1536464 is a reply to message #1535909] Tue, 30 December 2014 08:08 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi Nicolas

We used to share a single common Hudson instance with disastrous
intermittencies as shared files in temp collided.

Now there are many HIPPs, typically one per group of projects. The xtext
HIPP hosts those projects run by the itemis relengs.

So thank you to itemis for keeping EMF ticking over.

Regards

Ed Willink


On 30/12/2014 00:37, Nicolas Rouquette wrote:
> This is strange.
>
> I connected to the emf/org.eclipse.emf project with gerrit.
> After I pushed to gerrit, Hudson CI started a job that failed:
>
> https://hudson.eclipse.org/xtext/job/emf.gerrit/266/
>
> I'm surprised that the hudson config is defined in xtext.
> Is this normal?
>
> The job itself failed:
>
> https://hudson.eclipse.org/xtext/job/emf.gerrit/266/console
>
> It seems that there's a configuration problem somewhere.
>
> - Nicolas.
Re: OCL/QVTo standard library (was Re: Is there a known vulnerability with concurrent calls to Resou [message #1536633 is a reply to message #1535909] Tue, 30 December 2014 10:24 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33113
Registered: July 2009
Senior Member
Nicolas,

I'll have a look why the job is failing. Don't worry about that. I've
been a little inactive these past weeks for medical reasons...


On 30/12/2014 1:37 AM, Nicolas Rouquette wrote:
> This is strange.
>
> I connected to the emf/org.eclipse.emf project with gerrit.
> After I pushed to gerrit, Hudson CI started a job that failed:
>
> https://hudson.eclipse.org/xtext/job/emf.gerrit/266/
>
> I'm surprised that the hudson config is defined in xtext.
> Is this normal?
>
> The job itself failed:
>
> https://hudson.eclipse.org/xtext/job/emf.gerrit/266/console
>
> It seems that there's a configuration problem somewhere.
>
> - Nicolas.


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: OCL/QVTo standard library (was Re: Is there a known vulnerability with concurrent calls to Resou [message #1537347 is a reply to message #1536633] Tue, 30 December 2014 19:55 Go to previous message
Nicolas Rouquette is currently offline Nicolas RouquetteFriend
Messages: 40
Registered: December 2014
Member
Ok, take care.
Previous Topic:EMap performance compared to HashMap?
Next Topic:.ecore, XMLResource IDs and Xtext Builder
Goto Forum:
  


Current Time: Thu Mar 28 10:27:08 GMT 2024

Powered by FUDForum. Page generated in 0.06341 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top