eclipse-uml2 / uml2

An EMF-based implementation of the UML 2.x metamodel for the Eclipse platform.
Eclipse Public License 2.0
5 stars 4 forks source link

CME in ElementOperations.getStereotypeApplications #60

Open eclipse-uml2-bot opened 19 hours ago

eclipse-uml2-bot commented 19 hours ago

| --- | --- | | Bugzilla Link | 429486 | | Status | REOPENED | | Importance | P3 normal | | Reported | Mar 03, 2014 11:34 EDT | | Modified | Jun 24, 2014 01:39 EDT | | Version | 5.0.0 | | Reporter | Ed Willink |

Description

M5: When validating a UML profile model with a UML OCL body expression validator I get the CME below.

I suspect that this is another case of the DiagnosticDecorator introducing unexpected concurrency whereby the discovery of stereotypes correupts an iteration domain. It is probably necerssary to do some kind of brute force resolveAll for stereotypes before allowing the fine grained decoration processing to run.

(But at least I see nice markers on the OpaqueExpression etc.)

java.util.ConcurrentModificationException\ at org.eclipse.emf.common.util.AbstractEList$EIterator.checkModCount(AbstractEList.java:758)\ at org.eclipse.emf.common.util.AbstractEList$EIterator.doNext(AbstractEList.java:706)\ at org.eclipse.emf.common.util.AbstractEList$EIterator.next(AbstractEList.java:692)\ at org.eclipse.uml2.uml.internal.operations.ElementOperations.getStereotypeApplications(ElementOperations.java:206)\ at org.eclipse.uml2.uml.internal.impl.ElementImpl.getStereotypeApplications(ElementImpl.java:186)\ at org.eclipse.uml2.uml.edit.providers.ElementItemProvider.getChildren(ElementItemProvider.java:341)\ at org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider.getChildren(AdapterFactoryContentProvider.java:175)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator.decorate(DiagnosticDecorator.java:1440)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator.decorate(DiagnosticDecorator.java:1444)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator.decorate(DiagnosticDecorator.java:1444)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator.decorate(DiagnosticDecorator.java:1425)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator.redecorate(DiagnosticDecorator.java:1299)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator.handleDiagnostic(DiagnosticDecorator.java:1268)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator$DiagnosticDecoratorAdapter$Dispatcher.dispatch(DiagnosticDecorator.java:923)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator$DiagnosticDecoratorAdapter$Dispatcher.dispatch(DiagnosticDecorator.java:876)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator$DiagnosticDecoratorAdapter.updateDiagnostic(DiagnosticDecorator.java:977)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator$DiagnosticDecoratorAdapter.handleResourceDiagnostics(DiagnosticDecorator.java:998)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator$DiagnosticAdapter.notifyChanged(DiagnosticDecorator.java:223)\ at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:374)\ at org.eclipse.emf.ecore.resource.impl.ResourceImpl.load(ResourceImpl.java:1538)\ at org.eclipse.emf.ecore.resource.impl.ResourceImpl.load(ResourceImpl.java:1297)\ at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.demandLoad(ResourceSetImpl.java:259)\ at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.demandLoadHelper(ResourceSetImpl.java:274)\ at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.getResource(ResourceSetImpl.java:406)\ at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.getEObject(ResourceSetImpl.java:220)\ at org.eclipse.uml2.uml.util.UMLUtil.getProfile(UMLUtil.java:11270)\ at org.eclipse.uml2.uml.util.UMLUtil.getNamedElement(UMLUtil.java:11466)\ at org.eclipse.uml2.uml.util.UMLUtil.getNamedElement(UMLUtil.java:11416)\ at org.eclipse.uml2.uml.util.UMLUtil.getStereotype(UMLUtil.java:11478)\ at org.eclipse.uml2.uml.util.UMLUtil.getStereotype(UMLUtil.java:11505)\ at org.eclipse.uml2.uml.internal.operations.ElementOperations.getStereotypeApplications(ElementOperations.java:213)\ at org.eclipse.uml2.uml.internal.impl.ElementImpl.getStereotypeApplications(ElementImpl.java:186)\ at org.eclipse.uml2.uml.edit.providers.ElementItemProvider.getChildren(ElementItemProvider.java:341)\ at org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider.getChildren(AdapterFactoryContentProvider.java:175)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator.decorate(DiagnosticDecorator.java:1440)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator.decorate(DiagnosticDecorator.java:1444)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator.decorate(DiagnosticDecorator.java:1425)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator.redecorate(DiagnosticDecorator.java:1299)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator.handleDiagnostic(DiagnosticDecorator.java:1268)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator$DiagnosticDecoratorAdapter$Dispatcher.dispatch(DiagnosticDecorator.java:923)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator$DiagnosticDecoratorAdapter$Dispatcher.dispatch(DiagnosticDecorator.java:876)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator$DiagnosticDecoratorAdapter.updateDiagnostic(DiagnosticDecorator.java:977)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator$DiagnosticDecoratorAdapter.handleResourceDiagnostics(DiagnosticDecorator.java:998)\ at org.eclipse.emf.edit.ui.provider.DiagnosticDecorator$DiagnosticAdapter.notifyChanged(DiagnosticDecorator.java:223)\ at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:374)\ at org.eclipse.emf.ecore.resource.impl.ResourceImpl.load(ResourceImpl.java:1538)\ at org.eclipse.emf.ecore.resource.impl.ResourceImpl.load(ResourceImpl.java:1297)\ at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.demandLoad(ResourceSetImpl.java:259)\ at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.demandLoadHelper(ResourceSetImpl.java:274)\ at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.getResource(ResourceSetImpl.java:406)\ at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.getEObject(ResourceSetImpl.java:220)\ at org.eclipse.emf.ecore.util.EcoreUtil.resolve(EcoreUtil.java:198)\ at org.eclipse.emf.ecore.util.EcoreUtil.resolve(EcoreUtil.java:258)\ at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eResolveProxy(BasicEObjectImpl.java:1473)\ at org.eclipse.uml2.uml.internal.impl.ElementImportImpl.getImportedElement(ElementImportImpl.java:319)\ at org.eclipse.uml2.uml.internal.operations.ElementImportOperations.getName(ElementImportOperations.java:157)\ at org.eclipse.uml2.uml.internal.impl.ElementImportImpl.getName(ElementImportImpl.java:442)\ at org.eclipse.uml2.uml.edit.providers.ElementImportItemProvider.getText(ElementImportItemProvider.java:192)\ at org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider.getText(AdapterFactoryLabelProvider.java:421)\ at org.eclipse.emf.edit.ui.provider.DecoratingColumLabelProvider.getText(DecoratingColumLabelProvider.java:121)\ at org.eclipse.jface.viewers.ColumnLabelProvider.update(ColumnLabelProvider.java:37)\ at org.eclipse.jface.viewers.ViewerColumn.refresh(ViewerColumn.java:152)\ at org.eclipse.jface.viewers.AbstractTreeViewer.doUpdateItem(AbstractTreeViewer.java:959)\ at org.eclipse.jface.viewers.AbstractTreeViewer$UpdateItemSafeRunnable.run(AbstractTreeViewer.java:113)\ at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)\ at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49)\ at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:176)\ at org.eclipse.jface.viewers.AbstractTreeViewer.doUpdateItem(AbstractTreeViewer.java:1040)\ at org.eclipse.jface.viewers.StructuredViewer$UpdateItemSafeRunnable.run(StructuredViewer.java:489)\ at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)\ at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:49)\ at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:176)\ at org.eclipse.jface.viewers.StructuredViewer.updateItem(StructuredViewer.java:2180)\ at org.eclipse.jface.viewers.AbstractTreeViewer.createTreeItem(AbstractTreeViewer.java:851)\ at org.eclipse.jface.viewers.AbstractTreeViewer$1.run(AbstractTreeViewer.java:826)\ at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)\ at org.eclipse.jface.viewers.AbstractTreeViewer.createChildren(AbstractTreeViewer.java:800)\ at org.eclipse.jface.viewers.TreeViewer.createChildren(TreeViewer.java:670)\ at org.eclipse.jface.viewers.AbstractTreeViewer.createChildren(AbstractTreeViewer.java:771)\ at org.eclipse.jface.viewers.AbstractTreeViewer.handleTreeExpand(AbstractTreeViewer.java:1510)\ at org.eclipse.jface.viewers.TreeViewer.handleTreeExpand(TreeViewer.java:985)\ at org.eclipse.jface.viewers.AbstractTreeViewer$4.treeExpanded(AbstractTreeViewer.java:1522)\ at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:132)\ at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)\ at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4353)\ at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1061)\ at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1085)\ at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1070)\ at org.eclipse.swt.widgets.Tree.wmNotifyChild(Tree.java:7633)\ at org.eclipse.swt.widgets.Control.wmNotify(Control.java:5618)\ at org.eclipse.swt.widgets.Composite.wmNotify(Composite.java:1935)\ at org.eclipse.swt.widgets.Control.WM_NOTIFY(Control.java:5169)\ at org.eclipse.swt.widgets.Control.windowProc(Control.java:4666)\ at org.eclipse.swt.widgets.Display.windowProc(Display.java:5020)\ at org.eclipse.swt.internal.win32.OS.CallWindowProcW(Native Method)\ at org.eclipse.swt.internal.win32.OS.CallWindowProc(OS.java:2443)\ at org.eclipse.swt.widgets.Tree.callWindowProc(Tree.java:1553)\ at org.eclipse.swt.widgets.Tree.WM_LBUTTONDOWN(Tree.java:6501)\ at org.eclipse.swt.widgets.Control.windowProc(Control.java:4646)\ at org.eclipse.swt.widgets.Tree.windowProc(Tree.java:6024)\ at org.eclipse.swt.widgets.Display.windowProc(Display.java:5033)\ at org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method)\ at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:2549)\ at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3759)\ at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1122)\ at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)\ at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1006)\ at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:146)\ at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:615)\ at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)\ at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:566)\ at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:150)\ at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:125)\ at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)\ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:109)\ at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:80)\ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:372)\ at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:226)\ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\ at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)\ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\ at java.lang.reflect.Method.invoke(Method.java:601)\ at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:636)\ at org.eclipse.equinox.launcher.Main.basicRun(Main.java:591)\ at org.eclipse.equinox.launcher.Main.run(Main.java:1450)\ at org.eclipse.equinox.launcher.Main.main(Main.java:1426)

eclipse-uml2-bot commented 19 hours ago

By Kenn Hussey on Mar 07, 2014 14:08

Can you please provide a model or test case to reproduce this? I've not encountered it in my testing...

eclipse-uml2-bot commented 19 hours ago

By Ed Willink on Mar 09, 2014 11:41

The problem arises in the new (M6) (OCL) Validity View where traversal of UML ResourceSet to discover bodies provoked the UML Model Editor to behave concurrently.

Problem only arises on first validation. It can be suppressed by a an EcoreUtil.resolveAll() before starting validation.

The (sensible) EMF philosophy is that inter-thread concurrency integrity is an application issue. Unfortunately live validation makes the validation thread a concurrent application rather than a slave service and so requires a concurrency philosophy that is compatible with other threads. The UML lazy stereotype discovery was good for a slave service, but is proving very troublesome for concurrent applications.

eclipse-uml2-bot commented 19 hours ago

By Kenn Hussey on Mar 09, 2014 18:49

Thanks, Ed, but without a way to reproduce this in UML2 itself, I'm afraid I'll have to resolve it as "worksforme" and leave it to the application to solve or work around the problem.

eclipse-uml2-bot commented 19 hours ago

By Ed Willink on Mar 09, 2014 19:37

OK. So what is the policy that UML Live Validation pursues so that other concurrent applications can comply?

eclipse-uml2-bot commented 19 hours ago

By Kenn Hussey on Mar 09, 2014 21:04

(In reply to Ed Willink from comment #4)

OK. So what is the policy that UML Live Validation pursues so that other concurrent applications can comply?

I’m not sure I follow. The decoration in UML2 is manual, not live (per your request), so I don’t know what “policy” you refer to...

eclipse-uml2-bot commented 19 hours ago

By Ed Willink on Jun 23, 2014 10:50

This is still giving me a lot of trouble. (Live Validation is a red herring.)

The basic scenario is:

DiagnosticDecorator on main thread on behalf of UML Model Editor or some other UML-using editor.

(Xtext) Validation Job on a worker thread.

The worker thread discovers the stereotypes while the DiagnosticDecorator isn't looking.

What is the design policy that enables this concurrency conflict to be avoided?

a) is there a synchronization mutex that either the UML Model Editor doesn't activate or Validation doesn't observe?

b) is there a disable validation hook that should be routed to the Validator?

c) ...

Looking at Bug 405072#c11, the policy seems to be that anyone modifying a ResourceSet should synchronize on it. Proxy resolution is an EMF protocol largely hidden from users. UML exploits it for lazy profile loading. Consequently it seems that perhaps the bug is a missing synchronize around

getResources().add(result);\ \ in ResourceSetImpl.createResource. Looking at my lazy create UMLResource call stack, which is on yet another thread.

Thread [OCL VM] (Suspended (breakpoint at line 42 in UMLResourceImpl)) \ UMLResourceImpl.(URI) line: 42 \ UMLResourceFactoryImpl.createResourceGen(URI) line: 58 \ UMLResourceFactoryImpl.createResource(URI) line: 65 \ AdapterFactoryEditingDomain$AdapterFactoryEditingDomainResourceSet(ResourceSetImpl).createResource(URI, String) line: 434 \ AdapterFactoryEditingDomain$AdapterFactoryEditingDomainResourceSet(ResourceSetImpl).demandCreateResource(URI) line: 243 \ AdapterFactoryEditingDomain$AdapterFactoryEditingDomainResourceSet(ResourceSetImpl).getResource(URI, boolean) line: 400 \ AdapterFactoryEditingDomain$AdapterFactoryEditingDomainResourceSet(ResourceSetImpl).getEObject(URI, boolean) line: 220 \ EcoreUtil.resolve(EObject, ResourceSet) line: 199 \ EcoreUtil.resolve(EObject, EObject) line: 259 \ DynamicEObjectImpl(BasicEObjectImpl).eResolveProxy(InternalEObject) line: 1473 \ EObjectResolvingEList(EcoreEList).resolveProxy(EObject) line: 206 \ EObjectResolvingEList(EcoreEList).resolve(int, EObject) line: 161 \ EObjectResolvingEList.resolve(int, E) line: 60 \ EObjectResolvingEList(BasicEList).get(int) line: 348 \ AbstractEList$EIterator.doNext() line: 705 \ AbstractEList$EIterator.next() line: 692 \ PivotIdResolver(AbstractIdResolver).createOrderedSetOfAll(CollectionTypeId, Iterable) line: 440

I can't see any UML class that has access to the ResourceSet to synchronize it.

My PivotIdResolver could synchronize but its just an ordinary bit of object manipulation. Potentially every bit of 'read-only' application code that could actually be 'read-write' because of a proxy would need a synchronize. Quite unreasonable. A synchronize in EMF seems to be the solution.

If you agree please re-assign to EMF.

eclipse-uml2-bot commented 19 hours ago

By Kenn Hussey on Jun 23, 2014 11:28

(In reply to Ed Willink from comment #6)

What is the design policy that enables this concurrency conflict to be avoided?

I’m afraid I don’t know off-hand. :(

I can't see any UML class that has access to the ResourceSet to synchronize it.

That’s why I don’t think UML2 is the right place to address the problem.

My PivotIdResolver could synchronize but its just an ordinary bit of object manipulation. Potentially every bit of 'read-only' application code that could actually be 'read-write' because of a proxy would need a synchronize. Quite unreasonable. A synchronize in EMF seems to be the solution.

I doubt you’ll convince Ed (Merks) to add syncrhonization code in EMF. Unfortunately, the general guidance here is to add such synchronization code at the application level; whether that’s unreasonable or not is a matter of opinion.

eclipse-uml2-bot commented 19 hours ago

By Ed Willink on Jun 24, 2014 01:39

(In reply to Kenn Hussey from comment #7)

I doubt you’ll convince Ed (Merks) to add syncrhonization code in EMF. Unfortunately, the general guidance here is to add such synchronization code at the application level; whether that’s unreasonable or not is a matter of opinion.

I am aware of that. I don't want to change the very pragmatic "synchronization should be provided by the application at a higher level" from the EMF FAQ (http://wiki.eclipse.org/EMF/FAQ#Is_EMF_thread-safe.3F).

The problem is to identify where EMF becomes its own application. I'm currently experimenting with a missing "synchronized" in:

ResourceSetImpl.createResource override in AdapterFactoryEditingDomain.AdapterFactoryEditingDomainResourceSet (the EMF editing sub-application)

DiagnosticDecorator::redecorate (the EMF display sub-application)

IMHO It was the introduction of DiagnosticDecorator in EMF 2.9 that caused EMF to cross the "at a higher level" application threshold.