Bug 417765 - ImageDescriptorRegistry.hookDisplay() causes SWT Invalid thread access
Summary: ImageDescriptorRegistry.hookDisplay() causes SWT Invalid thread access
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 4.4   Edit
Hardware: All All
: P3 normal with 1 vote (vote)
Target Milestone: 4.4 M4   Edit
Assignee: Dani Megert CLA
QA Contact:
URL:
Whiteboard:
Keywords: needinfo
Depends on:
Blocks:
 
Reported: 2013-09-21 16:17 EDT by Bryan Hunt CLA
Modified: 2014-03-06 16:03 EST (History)
5 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Bryan Hunt CLA 2013-09-21 16:17:41 EDT
Eclipse Kepler

There appears to be a case where NewJavaProjectWizardPageTwo causes an SWT Invalid Thread Access when using Bndtools.  This problem has been reproduced by others.

To reproduce, create a new workspace, switch to the Bndtools perspective, create a new Bndtools OSGi project.  You should get the Invalid Thread Access.

The workaround is to delete the project you just created and create it again.

I believe the key here is that you have a brand new workspace.

Here is the stack trace.

org.eclipse.swt.SWTException: Invalid thread access
   at org.eclipse.swt.SWT.error(SWT.java:4397)
   at org.eclipse.swt.SWT.error(SWT.java:4312)
   at org.eclipse.swt.SWT.error(SWT.java:4283)
   at org.eclipse.swt.widgets.Display.error(Display.java:1204)
   at org.eclipse.swt.widgets.Display.checkDevice(Display.java:759)
   at org.eclipse.swt.widgets.Display.disposeExec(Display.java:1181)
   at org.eclipse.jdt.internal.ui.viewsupport.ImageDescriptorRegistry.hookDisplay(ImageDescriptorRegistry.java:77)
   at org.eclipse.jdt.internal.ui.viewsupport.ImageDescriptorRegistry.<init>(ImageDescriptorRegistry.java:40)
   at org.eclipse.jdt.internal.ui.JavaPlugin.internalGetImageDescriptorRegistry(JavaPlugin.java:954)
   at org.eclipse.jdt.internal.ui.JavaPlugin.getImageDescriptorRegistry(JavaPlugin.java:347)
   at org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListLabelProvider.<init>(CPListLabelProvider.java:68)
   at org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathsBlock.<init>(BuildPathsBlock.java:189)
   at org.eclipse.jdt.ui.wizards.JavaCapabilityConfigurationPage.getBuildPathsBlock(JavaCapabilityConfigurationPage.java:95)
   at org.eclipse.jdt.ui.wizards.JavaCapabilityConfigurationPage.init(JavaCapabilityConfigurationPage.java:151)
   at org.eclipse.jdt.ui.wizards.NewJavaProjectWizardPageTwo.initializeBuildPath(NewJavaProjectWizardPageTwo.java:318)
   at bndtools.wizards.project.NewBndProjectWizardPageTwo.initializeBuildPath(NewBndProjectWizardPageTwo.java:106)
   at org.eclipse.jdt.ui.wizards.NewJavaProjectWizardPageTwo.updateProject(NewJavaProjectWizardPageTwo.java:252)
   at org.eclipse.jdt.ui.wizards.NewJavaProjectWizardPageTwo.performFinish(NewJavaProjectWizardPageTwo.java:484)
   at org.eclipse.jdt.internal.ui.wizards.JavaProjectWizard.finishPage(JavaProjectWizard.java:82)
   at org.eclipse.jdt.internal.ui.wizards.NewElementWizard$2.run(NewElementWizard.java:118)
   at org.eclipse.jdt.internal.core.BatchOperation.executeOperation(BatchOperation.java:39)
   at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:728)
   at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2345)
   at org.eclipse.jdt.core.JavaCore.run(JavaCore.java:5331)
   at org.eclipse.jdt.internal.ui.actions.WorkbenchRunnableAdapter.run(WorkbenchRunnableAdapter.java:106)
   at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:121)
Comment 1 Neil Bartlett CLA 2013-09-21 16:58:43 EDT
I expect that you will need to know what the Bndtools method in that stack trace is doing. I will link to the full source at the bottom of this comment. In summary: we check whether a file called "bnd.bnd" already exists in the project, and if not create it. Then we just call the superclass implementation of the method.

Note that the entire of the rest of the stack trace is pure Eclipse/JDT. So my question is, why would a WizardPage method ever be called from a WorkbenchRunnable which is not running on the SWT main thread?

Also note that the exception happens during the call to the superclass method with the same signature. It seems clear that even if we hadn't extended this class or overridden the method, the exception would still have occurred.

Link to relevant Bndtools source code: https://github.com/bndtools/bndtools/blob/master/bndtools.core/src/bndtools/wizards/project/NewBndProjectWizardPageTwo.java
Comment 2 Noopur Gupta CLA 2013-09-24 06:34:52 EDT
similar to bug 96814, bug 182237, bug 125868 in the past.
Comment 3 Markus Keller CLA 2013-09-24 12:09:58 EDT
(In reply to Neil Bartlett from comment #1)
> So my question is, why would a WizardPage method ever be called from a
> WorkbenchRunnable which is not running on the SWT main thread?

finshPage(..) is run in a non-UI thread to ensure the UI stays responsive (progress updating) and the operation can be cancelled.

I think the problem eventually occurs because the NewBndProjectWizard doesn't add page NewJavaProjectWizardPageTwo. In the JavaProjectWizard, the second page is also created (i.e. createControl(..) is called) when the dialog is opened, and the ImageDescriptorRegistry is already created there, in the UI thread.

Bryan, can you test whether the exception from comment 0 is the only problem? Either comment out the code in ImageDescriptorRegistry#hookDisplay(), or set a breakpoint, and when it's hit, then select a trivial expression like "fDisplay" and choose context menu > Force Return.


(In reply to Noopur Gupta from comment #2)
> similar to bug 96814, bug 182237, bug 125868 in the past.

Adding more initialization calls in places where we know we're in the UI thread is not going to fix all these problems. I think a safer solution would be something like org.eclipse.debug.internal.ui.ImageDescriptorRegistry#hookDisplay(), which wraps the disposeExec in a fDisplay.asyncExec. And fRegistry should also be wrapped in a Collections.synchronizedMap(..).
Comment 5 Ferry Huberts CLA 2014-03-02 14:21:33 EST
(In reply to Dani Megert from comment #4)
> Fixed with
> http://git.eclipse.org/c/jdt/eclipse.jdt.ui.git/commit/
> ?id=4295c63aaffb3f40b0ece363de41c0015fe3f564
> 
> 
> Also fixed the same pattern in other components with:
> 
> http://git.eclipse.org/c/platform/eclipse.platform.debug.git/commit/
> ?id=8cd1c1abdcce26766e598687781fdf4edaee0e70
> 
> http://git.eclipse.org/c/jdt/eclipse.jdt.debug.git/commit/
> ?id=cd3805ebcc9f98c848a7aa99f6509e614a3a988a
> 
> http://git.eclipse.org/c/platform/eclipse.platform.git/commit/
> ?id=2415d4db592254c84cb133d8952828305844d98b

Dani,

Can we please please get this fix on Kepler?
Many of our (bndtools) users are running into it.
Comment 6 Dani Megert CLA 2014-03-04 11:37:03 EST
(In reply to Ferry Huberts from comment #5)
> Dani,
> 
> Can we please please get this fix on Kepler?
> Many of our (bndtools) users are running into it.

Kepler is done. The last service release was shipped last Friday.
Comment 7 Ferry Huberts CLA 2014-03-06 16:03:01 EST
(In reply to Dani Megert from comment #6)
> (In reply to Ferry Huberts from comment #5)
> > Dani,
> > 
> > Can we please please get this fix on Kepler?
> > Many of our (bndtools) users are running into it.
> 
> Kepler is done. The last service release was shipped last Friday.

That is rather disappointing. Now we have to tell our users not to use Kepler.

Can you then at least tell us how to work around it?