Bug 519596 - Accessing the ViewpointRegistry from a plugin activator creates a Display on the Component Resolve Thread
Summary: Accessing the ViewpointRegistry from a plugin activator creates a Display on ...
Status: NEW
Alias: None
Product: Sirius
Classification: Modeling
Component: Core (show other bugs)
Version: 5.0.0   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: Next   Edit
Assignee: Project inbox CLA
QA Contact:
URL:
Whiteboard: headless migration
Keywords: triaged
Depends on:
Blocks: 529263
  Show dependency tree
 
Reported: 2017-07-13 04:26 EDT by Jonathan Höges CLA
Modified: 2018-09-05 08:33 EDT (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Höges CLA 2017-07-13 04:26:51 EDT
The Application fails to start with an Invalid Thread Acces exception since the default display is associated with the Component Resolve Thread. Sirius version 5.0.1 on neon.3 and Java 8. The stack trace of the display creation by the ViewpointRegistry:
	at org.eclipse.swt.widgets.Display.<init>(Display.java:490)
	at org.eclipse.swt.widgets.Display.<init>(Display.java:481)
	at org.eclipse.swt.widgets.Display.getDefault(Display.java:1710)
	at org.eclipse.gmf.runtime.diagram.ui.preferences.AppearancePreferencePage.setDefaultFontPreference(AppearancePreferencePage.java:285)
	at org.eclipse.gmf.runtime.diagram.ui.preferences.AppearancePreferencePage.initDefaults(AppearancePreferencePage.java:222)
	at org.eclipse.sirius.diagram.ui.internal.preferences.DiagramAppearancePreferencePage.initDefaults(DiagramAppearancePreferencePage.java:205)
	at org.eclipse.sirius.diagram.ui.internal.preferences.DiagramUIPreferenceInitializer.initializeDefaultPreferences(DiagramUIPreferenceInitializer.java:29)
	at org.eclipse.core.internal.preferences.PreferenceServiceRegistryHelper$1.run(PreferenceServiceRegistryHelper.java:298)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.core.internal.preferences.PreferenceServiceRegistryHelper.runInitializer(PreferenceServiceRegistryHelper.java:301)
	at org.eclipse.core.internal.preferences.PreferenceServiceRegistryHelper.applyRuntimeDefaults(PreferenceServiceRegistryHelper.java:131)
	at org.eclipse.core.internal.preferences.PreferencesService.applyRuntimeDefaults(PreferencesService.java:370)
	at org.eclipse.core.internal.preferences.DefaultPreferences.applyRuntimeDefaults(DefaultPreferences.java:222)
	at org.eclipse.core.internal.preferences.DefaultPreferences.load(DefaultPreferences.java:276)
	at org.eclipse.core.internal.preferences.EclipsePreferences.create(EclipsePreferences.java:370)
	at org.eclipse.core.internal.preferences.EclipsePreferences.internalNode(EclipsePreferences.java:623)
	at org.eclipse.core.internal.preferences.EclipsePreferences.node(EclipsePreferences.java:766)
	at org.eclipse.core.internal.preferences.AbstractScope.getNode(AbstractScope.java:38)
	at org.eclipse.core.runtime.preferences.DefaultScope.getNode(DefaultScope.java:74)
	at org.eclipse.ui.preferences.ScopedPreferenceStore.getDefaultPreferences(ScopedPreferenceStore.java:237)
	at org.eclipse.ui.preferences.ScopedPreferenceStore.getPreferenceNodes(ScopedPreferenceStore.java:268)
	at org.eclipse.ui.preferences.ScopedPreferenceStore.internalGet(ScopedPreferenceStore.java:418)
	at org.eclipse.ui.preferences.ScopedPreferenceStore.getBoolean(ScopedPreferenceStore.java:358)
	at org.eclipse.sirius.common.ui.tools.internal.preference.DynamicConfigurationHelper.bindBoolean(DynamicConfigurationHelper.java:83)
	at org.eclipse.sirius.diagram.ui.provider.DiagramUIPlugin$Implementation$DynamicDiagramUIPreferences.<init>(DiagramUIPlugin.java:599)
	at org.eclipse.sirius.diagram.ui.provider.DiagramUIPlugin$Implementation.start(DiagramUIPlugin.java:174)
	at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:774)
	at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:1)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:767)
	at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:724)
	at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:932)
	at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:309)
	at org.eclipse.osgi.container.Module.doStart(Module.java:581)
	at org.eclipse.osgi.container.Module.start(Module.java:449)
	at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:470)
	at org.eclipse.osgi.internal.hooks.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:107)
	at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findLocalClass(ClasspathManager.java:529)
	at org.eclipse.osgi.internal.loader.ModuleClassLoader.findLocalClass(ModuleClassLoader.java:325)
	at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:345)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:423)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:372)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:364)
	at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:161)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at org.eclipse.osgi.internal.framework.EquinoxBundle.loadClass(EquinoxBundle.java:564)
	at org.eclipse.core.internal.registry.osgi.RegistryStrategyOSGI.createExecutableExtension(RegistryStrategyOSGI.java:174)
	at org.eclipse.core.internal.registry.ExtensionRegistry.createExecutableExtension(ExtensionRegistry.java:905)
	at org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(ConfigurationElement.java:243)
	at org.eclipse.core.internal.registry.ConfigurationElementHandle.createExecutableExtension(ConfigurationElementHandle.java:55)
	at org.eclipse.sirius.business.internal.migration.AbstractSiriusMigrationService.loadContributions(AbstractSiriusMigrationService.java:82)
	at org.eclipse.sirius.business.internal.migration.description.VSMMigrationService.<init>(VSMMigrationService.java:27)
	at org.eclipse.sirius.business.internal.migration.description.VSMMigrationService.<clinit>(VSMMigrationService.java:24)
	at org.eclipse.sirius.viewpoint.description.util.DescriptionResourceFactoryImpl.createResource(DescriptionResourceFactoryImpl.java:55)
	at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.createResource(ResourceSetImpl.java:434)
	at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.demandCreateResource(ResourceSetImpl.java:243)
	at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.getResource(ResourceSetImpl.java:400)
	at org.eclipse.sirius.business.api.componentization.ViewpointRegistryImpl.load(ViewpointRegistryImpl.java:651)
	at org.eclipse.sirius.business.api.componentization.ViewpointRegistryImpl.load(ViewpointRegistryImpl.java:636)
	at org.eclipse.sirius.business.api.componentization.ViewpointRegistryImpl.refreshComponentsFromWorkspace(ViewpointRegistryImpl.java:547)
	at org.eclipse.sirius.business.api.componentization.ViewpointRegistryImpl.init(ViewpointRegistryImpl.java:183)
	at org.eclipse.sirius.business.api.componentization.ViewpointRegistry$ViewpointRegistryHolder.<clinit>(ViewpointRegistry.java:138)
	at org.eclipse.sirius.business.api.componentization.ViewpointRegistry.getInstance(ViewpointRegistry.java:120)
My plugin activator calling ViewpointRegistry.getInstance
	at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:774)
	at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:1)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:767)
	at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:724)
	at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:932)
	at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:309)
	at org.eclipse.osgi.container.Module.doStart(Module.java:581)
	at org.eclipse.osgi.container.Module.start(Module.java:449)
	at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:470)
	at org.eclipse.osgi.internal.hooks.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:107)
	at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findLocalClass(ClasspathManager.java:529)
	at org.eclipse.osgi.internal.loader.ModuleClassLoader.findLocalClass(ModuleClassLoader.java:325)
	at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:345)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:423)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:372)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:364)
	at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:161)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at org.eclipse.osgi.internal.framework.EquinoxBundle.loadClass(EquinoxBundle.java:564)
	at org.eclipse.equinox.internal.ds.model.ServiceComponent.createInstance(ServiceComponent.java:493)
	at org.eclipse.equinox.internal.ds.model.ServiceComponentProp.createInstance(ServiceComponentProp.java:270)
	at org.eclipse.equinox.internal.ds.model.ServiceComponentProp.build(ServiceComponentProp.java:331)
	at org.eclipse.equinox.internal.ds.InstanceProcess.buildComponent(InstanceProcess.java:620)
	at org.eclipse.equinox.internal.ds.InstanceProcess.buildComponents(InstanceProcess.java:197)
	at org.eclipse.equinox.internal.ds.Resolver.buildNewlySatisfied(Resolver.java:473)
	at org.eclipse.equinox.internal.ds.Resolver.enableComponents(Resolver.java:217)
	at org.eclipse.equinox.internal.ds.SCRManager.performWork(SCRManager.java:816)
	at org.eclipse.equinox.internal.ds.SCRManager$QueuedJob.dispatch(SCRManager.java:783)
	at org.eclipse.equinox.internal.ds.WorkThread.run(WorkThread.java:89)
	at java.lang.Thread.run(Thread.java:748)

Stacktrace of the subsequent error:
org.eclipse.swt.SWTException: Invalid thread access
	at org.eclipse.swt.SWT.error(SWT.java:4533)
	at org.eclipse.swt.SWT.error(SWT.java:4448)
	at org.eclipse.swt.SWT.error(SWT.java:4419)
	at org.eclipse.swt.widgets.Display.error(Display.java:1262)
	at org.eclipse.swt.widgets.Display.checkDevice(Display.java:766)
	at org.eclipse.swt.widgets.Display.addListener(Display.java:627)
	at org.eclipse.ui.internal.ide.application.IDEWorkbenchAdvisor.<init>(IDEWorkbenchAdvisor.java:171)
	at org.eclipse.ui.internal.ide.application.IDEWorkbenchAdvisor.<init>(IDEWorkbenchAdvisor.java:179)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:139)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:388)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:243)
	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:673)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:610)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1519)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1492)
Comment 1 Maxime Porhel CLA 2017-07-13 05:04:53 EDT
Hi Jonathan, 

Could you give us more details about the VSM (.odesign files) you have in your workspace or deployed ?
Which bundle do you use ? And/or how did you install Sirius in it ? 

Regards

Maxime
Comment 2 Maxime Porhel CLA 2017-07-13 05:44:49 EDT
It seems that your Activator is triggered from the declarative service initialization. 

The ViewpointRegistry initialization triggers the load of all Sirius plugins declaring migration participants, some of them are currently in UI plugins (often due to historical reasons). Then those UI plugins like DiagramUIPlugin plugin can trigger the access of a display even during initialization (like the default font preference from GMF)
Comment 3 Jonathan Höges CLA 2017-07-13 06:07:01 EDT
(In reply to Maxime Porhel from comment #1)
> Hi Jonathan, 
> 
> Could you give us more details about the VSM (.odesign files) you have in
> your workspace or deployed ?
> Which bundle do you use ? And/or how did you install Sirius in it ? 
> 
> Regards
> 
> Maxime

After seeing the migration service in the call stack, i manually migrated the odesign to file version 12.0.0.2017041100, but the behavior still occurs since it checks whether migration is necessary. Begin of the odesign:
<?xml version="1.0" encoding="UTF-8"?>
<description:Group xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:description="http://www.eclipse.org/sirius/description/1.1.0" xmlns:description_1="http://www.eclipse.org/sirius/diagram/description/1.1.0" xmlns:properties="http://www.eclipse.org/sirius/properties/1.0.0" xmlns:properties-ext-widgets-reference="http://www.eclipse.org/sirius/properties/1.0.0/ext/widgets/reference" xmlns:style="http://www.eclipse.org/sirius/diagram/description/style/1.1.0" xmlns:tool="http://www.eclipse.org/sirius/diagram/description/tool/1.1.0" xmlns:tool_1="http://www.eclipse.org/sirius/description/tool/1.1.0" name="fbdesigner" version="12.0.0.2017041100">
<ownedViewpoints ...

I'm not sure what you mean by the used bundle or installing Sirius in it.
Comment 4 Maxime Porhel CLA 2017-07-13 07:40:22 EDT
Is the Activator which accesses the ViewpointRegistry an activator of a Viewpoint Specification Project ? (In this case it weird because we never had a stack like this)

Otherwise could you give us more hints about your activator ? 
Which class triggers the following part of the stack ? 

>	at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:161)
>	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
>	at org.eclipse.osgi.internal.framework.EquinoxBundle.loadClass(EquinoxBundle.java:564)
>	at org.eclipse.equinox.internal.ds.model.ServiceComponent.createInstance(ServiceComponent.java:493)
Comment 5 Pierre-Charles David CLA 2017-12-07 03:00:03 EST
Moving to 6.0 for further analysis, but it looks like the root of the issue is that some of our migration participants are in UI plug-ins.

From what I understand, the process is:
* some code tries to access the ViewpointRegistry while the UI is not present or not yet initialized. This should not be a problem, there's no good reason to require a UI at all to use to registry;
* the registry tries to load all the registered VSMs;
* this triggers the migration process, which itself will try to initialize all participants;
* some of these are defined in ui plug-ins, and part of the initialization of these plug-ins try to access the UI, which fails.

If this analysis is confirmed, there are several steps we should do:
* move all the migration participants which do not actually require a UI into a non-UI plugins. This should be most of them, but it's possible some "migrations" are actually fixes for layout issues in older versions, which may require off-screen "graphical" operations which can be hard to do in pure headless mode. If this happens it should only occur for aird migrations, not VSMs, but still we should be able to *load* any aird without a UI present.
* change the migration participant extension point to move the "from => to" version metadata out of the Java code and directly in the extension definition: this would allow the migration process to filter participants which are not needed and only instantiate the ones required given the model versions actually seen. This might not prevent the initialization of the plug-in if another participant defined there is needed, but it can help.
* see if we can avoid the UI requirement on the particular plug-in initialization path in the stack, either at the DiagramUIPlugin$Implementation.start() level or at DiagramUIPreferenceInitializer.initializeDefaultPreferences() (and possibly others lurking behind).
Comment 6 Pierre-Charles David CLA 2017-12-07 03:03:21 EST
(In reply to Pierre-Charles David from comment #5)
> * some code tries to access the ViewpointRegistry while the UI is not
> present or not yet initialized.

Actually, it may very well be present and initialized in this particular case, and the immediate issue may just be that we're doing non-UI work in the UI thread (which could maybe be "fixed" by a well-placed Display.syncExec()), but this still highlight the overall problem that accessing the registry and plain loading of VSMs may need a UI at all.
Comment 7 Maxime Porhel CLA 2017-12-18 09:48:21 EST
I mark this issue as triaged as we moved it to 6.0 for further analysis.

Note that there is no clear steps to reproduce but "this still highlight the overall problem that accessing the registry and plain loading of VSMs may need a UI at all" as written by Pierre-Charles. 

Note that regarding the analysis result, this issue might still be removed from the 6.0.0 milestone.
Comment 8 Eclipse Genie CLA 2018-01-09 05:27:39 EST
New Gerrit change created: https://git.eclipse.org/r/115097