Bug 513145 - NPE in DeferredLayoutCommand when adding semantic elements from an Xtext editor
Summary: NPE in DeferredLayoutCommand when adding semantic elements from an Xtext editor
Status: NEW
Alias: None
Product: Sirius
Classification: Modeling
Component: Diagram (show other bugs)
Version: 4.0.0   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: Next   Edit
Assignee: Laurent Fasani CLA
QA Contact:
URL:
Whiteboard:
Keywords: triaged
Depends on:
Blocks: 507026
  Show dependency tree
 
Reported: 2017-03-06 07:07 EST by Eirik Grønsund CLA
Modified: 2019-10-08 14:16 EDT (History)
7 users (show)

See Also:


Attachments
Stack trace of the NPE occuring in the DeferredLayoutCommand (134.29 KB, image/png)
2017-03-06 07:07 EST, Eirik Grønsund CLA
no flags Details
Screencast reproducing the problem (7.89 MB, image/gif)
2018-11-27 03:31 EST, Tamas Miklossy CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Eirik Grønsund CLA 2017-03-06 07:07:08 EST
Created attachment 267112 [details]
Stack trace of the NPE occuring in the DeferredLayoutCommand

Adding and saving a semantic element from a Xtext editor when a corresponding Sirius diagram editor is open leads to a NPE when Sirius is updating the layout of the diagram involving the added element. 

The parent or root EditPart (in AbstractEditPart) is null, most likely because the diagram is open but not active when saving from the Xtext editor.

Reproduce by adding and saving a semantic element from a Xtext editor while an open diagram in Sirius is rendering the element.

I have not been able to reproduce the error when adding a semantic element from an EMF editor.
Comment 1 Steve Monnier CLA 2017-03-10 09:08:20 EST
Hello,

Can you provide a sample with the XText editor so we can reproduce the issue?

We are currently busy working on the M6 release, I do not know when we will be able to look into this issue.

Regards,
Steve
Comment 2 Eirik Grønsund CLA 2017-04-05 07:19:25 EDT
(In reply to Steve Monnier from comment #1)
> Hello,
> 
> Can you provide a sample with the XText editor so we can reproduce the issue?
> 
> We are currently busy working on the M6 release, I do not know when we will
> be able to look into this issue.
> 
> Regards,
> Steve

Hello,

I've created a Xtext project from the "Five simple steps to your JVM language" tutorial and added a minimal specification and representation bundle.

You can clone or fork it from:

https://github.com/eirikg/XbaseSiriusIntegration

There is readme.txt file at the root of the org.example.domainmodel bundle project descibing how to reproduce.

Hope you can use it to verify the exception.
Comment 3 Steve Monnier CLA 2017-04-10 10:41:25 EDT
Hello Eirik,

Thanks for your sample, I have been able to reproduce your issue.
I have a fix that I just pushed to Gerrit (https://git.eclipse.org/r/#/c/94761/). We will try to review and integrated it as soon as possible.

Regards,
Steve
Comment 4 Eclipse Genie CLA 2017-04-10 10:42:08 EDT
New Gerrit change created: https://git.eclipse.org/r/94761
Comment 5 Steve Monnier CLA 2017-05-05 10:22:28 EDT
Hello,

The fix is not as simple as the previous gerrit which causes some regressions. Unfortunately, we do not know when we will look into it as we are currently focused on the Sirius 5.0 release.

Regards,
Steve
Comment 6 Jonathan Pepin CLA 2018-04-18 09:04:08 EDT
Hello,

I have the same problem (identical stack trace).
I tested on last version of Sirius 4 and Sirius 5.

I tested the bug fix, it resolve the NPE.

When do you plan to apply a correction ?

Best,
Jonathan
Comment 7 Laurent Fasani CLA 2018-04-19 08:45:13 EDT
Hello Jonathan
I am currently working on this bug.

The fix looks correct and I expect it to be available on Sirius 6.0.0 soon.
Comment 8 Laurent Fasani CLA 2018-04-20 08:01:44 EDT
This fix consists in executing the code instead of calling a Display.asyncExec to execute the code.

I am not able to guarantee that SiriusCanonicalLayoutCommand is called in a context where it would be executed on the UIThread.
So, a safer fix would be that the code of SiriusCanonicalLayoutCommand.doExecute would be done on UIThread and with syncExec, calling Display.syncExec

Concerning the junit test, i was not able to reproduce the issue with a non xtext context. I tried to do an external change of the dmodel(mode semantic) with a emf reflexive editor but in that case the issue does not occur. The difference I can see is that, in that case, the JvmGenericType  object are not created. If the change is done in an xtext editor, that JvmGenericType are created by the Xtext builder.

So the conclusion is that, in the case of the issue, the SiriusCanonicalLayoutCommand.doExecute content calls code in asyncExec which let the xtext builder create JvmGenericType before the job is called which probably do indirect effects on the EditPart model of the sirius editor.
So for now I will not provide a junit test fot that fix.
Comment 9 Eclipse Genie CLA 2018-04-23 10:57:49 EDT
New Gerrit change created: https://git.eclipse.org/r/121576
Comment 10 Eclipse Genie CLA 2018-04-23 12:10:46 EDT
New Gerrit change created: https://git.eclipse.org/r/121585
Comment 11 Laurent Fasani CLA 2018-04-24 12:02:40 EDT
Could SiriusCanonicalLayoutCommand be a precommit listener?
SiriusCanonicalLayoutCommand uses, at the end, the gmf DeferredLayoutCommand which requires the EditPart to be created. The editPart are created only in the post commit(too late).
That's why SiriusCanonicalLayoutCommand is called by a OperationHistoryListener after post the commit.
So it can not a precommit listener and then the attempt on commit https://git.eclipse.org/r/121576 is hopeless. It would require some changes:
- do without EditPart
- make sure that layout computation on NodeContainer or Compartment (particularly in autosize) does not require some Figure to be created. That's a big work.

Layouting : SiriusCanonicalLayoutCommand.doExecute() implementation alternatives
1 using Display.async is at the origin of this ticket and causes NPE
2 using Display.sync make some tests to fail in dead lock before refresh that is called from swtbot code on a no UIThread. We could accept making the supposition that, on a runtime(not from test), refresh or other kind of code that require the UI is, in fact, called on UIThread. We can hon
3 calling the code directly is not a good idea because in some particular case of layout with container in autosize when need some draw2d figure to layout properly.
Comment 12 Laurent Fasani CLA 2018-04-25 06:05:29 EDT
I went deeper in proposal 2 (Display.syncExec)
To avoid dead lock, it is possible to avoid dead lock calling refreshDiagram from UI Thread and not directly from swt test code.

But unfortunately, the refresh code is also called on no UIThread by Sirius code: when click on refresh on a diagram, we are on UIThread using ProgressMonitorDialog.
We call monitorDialog.run(true, false, new RefreshRunnableWithProgress(editParts)). The first boolean indicates that it is forked, that is is executed on non UI Thread.
RefreshRunnableWithProgress will do the refresh and then the SiriusCanonicalLayoutCommand is called. then Display.syncExec is called then Lock.uiAcquire in EMFT that require the UI

Dead lock : ProgressMonitorDialog waits for RefreshRunnableWithProgress to finish and RefreshRunnableWithProgress wait for UIThread.
Comment 13 Pierre-Charles David CLA 2018-05-16 09:54:17 EDT
I'll try to have one last look if I can get the time in the next few days, but so far all our attempts to integrate a fix have very bad side effects on other scenarios (e.g. deadlocks), and our current understanding is that fixing this correctly would require deep changes.

Most probably the ticket will be moved to 6.1 (planned for this autumn). Hopefully the analysis we've now done will allow us to make a concrete plan to fix the underlying issues instead of moving it again next time.
Comment 14 Pierre-Charles David CLA 2018-05-24 02:35:52 EDT
Moving to 6.1, sorry. It doesn't seem like we'll be able to have another look before the 6.0 release (which is coming soon).
Comment 15 Tamas Miklossy CLA 2018-11-27 03:30:22 EST
I have also encountered this problem recently while trying out the Xtext-Example statemachine project available under https://github.com/ObeoNetwork/Xtext-Sirius-integration. 

Stacktrace:

null
org.eclipse.ui
Error
Tue Nov 27 08:36:16 CET 2018
Unhandled event loop exception

java.lang.NullPointerException
	at org.eclipse.gef.editparts.AbstractEditPart.createChild(AbstractEditPart.java:269)
	at org.eclipse.gef.editparts.AbstractEditPart.refreshChildren(AbstractEditPart.java:780)
	at org.eclipse.gef.editparts.AbstractEditPart.refresh(AbstractEditPart.java:726)
	at org.eclipse.gef.editparts.AbstractGraphicalEditPart.refresh(AbstractGraphicalEditPart.java:644)
	at org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart.access$3(GraphicalEditPart.java:1)
	at org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart$3.run(GraphicalEditPart.java:861)
	at org.eclipse.emf.transaction.impl.TransactionalEditingDomainImpl.runExclusive(TransactionalEditingDomainImpl.java:328)
	at org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart.refresh(GraphicalEditPart.java:851)
	at org.eclipse.gmf.runtime.diagram.ui.commands.DeferredLayoutCommand$1.run(DeferredLayoutCommand.java:146)
	at org.eclipse.gmf.runtime.diagram.ui.util.EditPartUtil.synchronizeRunnableToMainThread(EditPartUtil.java:106)
	at org.eclipse.gmf.runtime.diagram.ui.commands.DeferredLayoutCommand.doExecuteWithResult(DeferredLayoutCommand.java:186)
	at org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand.doExecute(AbstractTransactionalCommand.java:247)
	at org.eclipse.emf.workspace.AbstractEMFOperation.execute(AbstractEMFOperation.java:150)
	at org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy.execute(ICommandProxy.java:68)
	at org.eclipse.gef.commands.CompoundCommand.execute(CompoundCommand.java:129)
	at org.eclipse.sirius.diagram.ui.internal.refresh.layout.SiriusCanonicalLayoutCommand.executeLayoutDueToExternalChanges(SiriusCanonicalLayoutCommand.java:109)
	at org.eclipse.sirius.diagram.ui.internal.refresh.layout.SiriusCanonicalLayoutCommand.access$3(SiriusCanonicalLayoutCommand.java:106)
	at org.eclipse.sirius.diagram.ui.internal.refresh.layout.SiriusCanonicalLayoutCommand$1.run(SiriusCanonicalLayoutCommand.java:92)
	at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:40)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:185)
	at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3933)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3564)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1173)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1062)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:156)
	at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:628)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:563)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:151)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:155)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:199)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:137)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:107)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:391)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:246)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:659)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:595)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1501)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1474)
Comment 16 Tamas Miklossy CLA 2018-11-27 03:31:14 EST
Created attachment 276714 [details]
Screencast reproducing the problem