Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 318896 - Transition with guard causes reload of a closing resource
Summary: Transition with guard causes reload of a closing resource
Status: RESOLVED WONTFIX
Alias: None
Product: MDT.UML2
Classification: Modeling
Component: Core (show other bugs)
Version: unspecified   Edit
Hardware: PC All
: P3 major (vote)
Target Milestone: ---   Edit
Assignee: UML2 Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-07-05 09:59 EDT by Adam Neal CLA
Modified: 2012-08-29 11:33 EDT (History)
1 user (show)

See Also:


Attachments
don't call eGet with resolve=true during 'remove' (2.50 KB, patch)
2010-07-05 10:02 EDT, Adam Neal CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Adam Neal CLA 2010-07-05 09:59:06 EDT
Build Identifier: IES 3.6, UML 2.2

The implementation of the SubsetSupersetEObjectContainmentWithInverseEList causes eGet() (which defaults to resolve=true) when trying to clear the list of guards.  Because of this call, eGet actually re-resolves the resource which may be in the process of closing.  This leaves the fragment in a bad state (the resource is unloaded, yet its flag is still set to isLoaded=true).  This can cause big problems when there are clients who perform postLoad behaviour on newly loaded resources since EObjects existing in the poorly closed resource will not be resolvable and thus look deleted.

The following trace shows what happens when I try to close a fragmented class object that contains a transition with a guard.  The trace shows that the fragment is being closed, but as the guards are being cleared, it forces a reload, and we end up in RMPResource.load() again, which should not be happening.

Thread [main] (Suspended (breakpoint at line 1285 in RMPResource))    
    RMPResource.load(Map<?,?>) line: 1285    
    MSLEditingDomain$MSLResourceSet(ResourceSetImpl).demandLoad(Resource) line: 255    
    MSLEditingDomain$MSLResourceSet(ResourceSetImpl).demandLoadHelper(Resource) line: 270    
    MSLEditingDomain$MSLResourceSet(ResourceSetImpl).getResource(URI, boolean) line: 354    
    MSLEditingDomain$MSLResourceSet.getResource(URI, boolean) line: 2444    
    MSLEditingDomain$MSLResourceSet(ResourceSetImpl).getEObject(URI, boolean) line: 216    
    EcoreUtil.resolve(EObject, ResourceSet) line: 202    
    EcoreUtil.resolve(EObject, EObject) line: 262    
    TransitionImpl(BasicEObjectImpl).eResolveProxy(InternalEObject) line: 1483    
    TransitionImpl.getGuard() line: 643    
    TransitionImpl.eGet(int, boolean, boolean) line: 1192    
    TransitionImpl(BasicEObjectImpl).eGet(EStructuralFeature, boolean, boolean) line: 1021    
    TransitionImpl(BasicEObjectImpl).eGet(EStructuralFeature, boolean) line: 1013    
    TransitionImpl(BasicEObjectImpl).eGet(EStructuralFeature) line: 1008    
    SubsetSupersetEObjectContainmentWithInverseEList$Resolving<E>(SubsetSupersetEObjectEList<E>).subsetRemove(Object) line: 164    
    SubsetSupersetEObjectContainmentWithInverseEList$Resolving<E>(SubsetSupersetEObjectEList<E>).didRemove(int, E) line: 255    
    SubsetSupersetEObjectContainmentWithInverseEList$Resolving<E>(AbstractEList<E>).didClear(int, Object[]) line: 172    
    SubsetSupersetEObjectContainmentWithInverseEList$Resolving<E>(BasicEList<E>).clear() line: 646    
    SubsetSupersetEObjectContainmentWithInverseEList$Resolving<E>(NotifyingListImpl<E>).doClear() line: 1155    
    SubsetSupersetEObjectContainmentWithInverseEList$Resolving<E>(NotifyingListImpl<E>).clear() line: 1082    
    TransitionImpl.eUnset(int) line: 1317    
    TransitionImpl(BasicEObjectImpl).eUnset(EStructuralFeature) line: 1164    
    RMPResourceUtil.unloaded(EObject) line: 130    
    RMPResourceUtil.unloaded(EObject) line: 123    
    RMPResourceUtil.unloaded(EObject) line: 123    
    RMPResourceUtil.unloaded(EObject) line: 123    
    RMPResourceUtil.unload(Resource) line: 101    
    UMLResourceUtil.unload(Resource) line: 562    
    CloseFragmentsCommand(CloseResourcesCommand).unloadResource(Resource) line: 599    
    CloseFragmentsCommand(CloseResourcesCommand).unloadResources(List<Resource>) line: 594    
    CloseFragmentsCommand(CloseResourcesCommand).closeResources(IProgressMonitor) line: 274    
    CloseFragmentActionDelegate$1.run() line: 57    
    MSLEditingDomain$1(MSLTransactionalEditingDomain).runExclusive(Runnable) line: 343    
    MSLEditingDomain.runExclusive(Runnable) line: 2746    
    CloseFragmentActionDelegate.doRun(IProgressMonitor) line: 53    
    CloseFragmentActionDelegate(AbstractActionDelegate).run(IProgressMonitor) line: 391    
    AbstractModelActionDelegate.access$0(AbstractModelActionDelegate, IProgressMonitor) line: 1    
    AbstractModelActionDelegate$1.run() line: 73    
    MSLEditingDomain$1(MSLTransactionalEditingDomain).runExclusive(Runnable) line: 343    
    MSLEditingDomain.runExclusive(Runnable) line: 2746    
    CloseFragmentActionDelegate(AbstractModelActionDelegate).run(IProgressMonitor) line: 70    
    ActionManager$1.run() line: 225    
    BusyIndicator.showWhile(Display, Runnable) line: 70    
    ActionManager.run(IActionWithProgress) line: 223    
    CloseFragmentActionDelegate(AbstractActionDelegate).run(IAction) line: 233    
    ObjectPluginAction(PluginAction).runWithEvent(Event) line: 251    
    PluginActionContributionItem(ActionContributionItem).handleWidgetSelection(Event, boolean) line: 584    
    ActionContributionItem.access$2(ActionContributionItem, Event, boolean) line: 501    
    ActionContributionItem$5.handleEvent(Event) line: 411    
    EventTable.sendEvent(Event) line: 84    
    MenuItem(Widget).sendEvent(Event) line: 1234    
    Display.runDeferredEvents() line: 3540    
    Display.readAndDispatch() line: 3159    
    Workbench.runEventLoop(Window$IExceptionHandler, Display) line: 2629    
    Workbench.runUI() line: 2593    
    Workbench.access$4(Workbench) line: 2427    
    Workbench$7.run() line: 670    
    Realm.runWithDefault(Realm, Runnable) line: 332    
    Workbench.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 663    
    PlatformUI.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 149    
    IDEApplication.start(IApplicationContext) line: 115    
    EclipseAppHandle.run(Object) line: 196    
    EclipseAppLauncher.runApplication(Object) line: 110    
    EclipseAppLauncher.start(Object) line: 79    
    EclipseStarter.run(Object) line: 369    
    EclipseStarter.run(String[], Runnable) line: 179    
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]    
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39    
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 37    
    Method.invoke(Object, Object...) line: 599    
    Main.invokeFramework(String[], URL[]) line: 619    
    Main.basicRun(String[]) line: 574    
    Main.run(String[]) line: 1407    
    Main.main(String[]) line: 1383    


Reproducible: Always

Steps to Reproduce:
1. Create a class, add a state machine, add transition with a guard + code
2. Fragment the class
3. close the fragmented class

- The class will not close.
Comment 1 Adam Neal CLA 2010-07-05 10:02:12 EDT
Created attachment 173432 [details]
don't call eGet with resolve=true during 'remove'

Attaching a patch that resolves the issue.
Comment 2 Kenn Hussey CLA 2010-07-08 13:31:25 EDT
Please provide a test case that can be use to produce this problem in open source. Things like "fragment the class" and "close the fragmented class" don't make sense from an open source UML2 perspective.

The proposed patch would introduce other problems; for example, the inability to remove an element from the list in the event that the list was not previously resolved.
Comment 3 Christian Damus CLA 2012-08-29 09:20:56 EDT
I don't think this is a bug in the UML2 subset-superset list implementation.  It's a bug in the RMPResourceUtil class (which is not from Eclipse UML2).  Look at this part of the stack trace:

    SubsetSupersetEObjectContainmentWithInverseEList$Resolving<E>(NotifyingListImpl<E>).clear() line: 1082    
    TransitionImpl.eUnset(int) line: 1317    
    TransitionImpl(BasicEObjectImpl).eUnset(EStructuralFeature) line: 1164    
    RMPResourceUtil.unloaded(EObject) line: 130    
    ...
    RMPResourceUtil.unload(Resource) line: 101    
    UMLResourceUtil.unload(Resource) line: 562    
    CloseFragmentsCommand(CloseResourcesCommand).unloadResource(Resource) line: 

The RMPResourceUtil is interfering with the unloading of a resource by unsetting a feature of some object that was unloaded.  This is not correct.  Objects are changed into proxies by the unloading of an EMF resource, and that's all.
Comment 4 Kenn Hussey CLA 2012-08-29 11:33:19 EDT
Given Christian's comment (thanks for looking into this!), it's not likely we'll be making a change in UML2.