Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 374121

Summary: AIOOBE when restoring a window with no perspectives
Product: [Eclipse Project] Platform Reporter: Brian de Alwis <bsd>
Component: UIAssignee: Brian de Alwis <bsd>
Status: VERIFIED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: bsd, emoffatt, Michael_Rennie, mvi, pwebster, tom.schindl
Version: 4.2Flags: emoffatt: review+
bsd: review+
Target Milestone: 4.2 RC1   
Hardware: All   
OS: All   
Whiteboard:
Bug Depends on:    
Bug Blocks: 377394    
Attachments:
Description Flags
Sample program demonstrating the issue
none
Stacktrace from the IDE before it renders the StatusLine
none
Stacktrace from an app with no perspectives
none
Patch to create WorkbenchWindow after MWindow has been realized
none
Updated patch
none
Alternative patch none

Description Brian de Alwis CLA 2012-03-13 13:57:02 EDT
We're working on a platform-style product where the base level product has no default perspective.  We've noticed 2 exceptions like the following on subsequent startups.

In this case, we're trying to render the following control:

org.eclipse.e4.ui.model.application.ui.menu.impl.ToolControlImpl@57125f92 (elementId: org.eclipse.ui.StatusLine, tags: [stretch], contributorURI: null) (widget: null, renderer: org.eclipse.e4.ui.workbench.renderers.swt.ToolControlRenderer@4bc78066, toBeRendered: true, onTop: false, visible: true, containerData: null, accessibilityPhrase: null) (contributionURI: bundleclass://org.eclipse.ui.workbench/org.eclipse.ui.internal.StandardTrim, object: org.eclipse.ui.internal.StandardTrim@16becf68)

The tool control object is created, but line 82 of org.eclipse.ui.internal.StandardTrim does not actually create the status line widget as the context doesn't have a corresponding IWorkbenchWindow.

!ENTRY org.eclipse.e4.ui.workbench.swt 4 2 2012-03-13 13:34:00.012
!MESSAGE Problems occurred when invoking code from plug-in: "org.eclipse.e4.ui.workbench.swt".
!STACK 0
java.lang.ArrayIndexOutOfBoundsException: -1
	at org.eclipse.e4.ui.workbench.renderers.swt.ToolControlRenderer.createWidget(ToolControlRenderer.java:71)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createWidget(PartRenderingEngine.java:882)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:616)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:718)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$2(PartRenderingEngine.java:689)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$7.run(PartRenderingEngine.java:683)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:668)
	at org.eclipse.e4.ui.workbench.renderers.swt.SWTPartRenderer.processContents(SWTPartRenderer.java:59)
	at org.eclipse.e4.ui.workbench.renderers.swt.TrimBarRenderer.processContents(TrimBarRenderer.java:154)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:628)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$6.run(PartRenderingEngine.java:505)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:490)
	at org.eclipse.e4.ui.workbench.renderers.swt.WBWRenderer.processContents(WBWRenderer.java:647)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:628)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:718)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$2(PartRenderingEngine.java:689)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$7.run(PartRenderingEngine.java:683)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:668)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:954)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:909)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:85)
	at org.eclipse.ui.internal.Workbench$4.run(Workbench.java:580)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:535)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
	at com.lgc.ds.rcp.DSApplication.start(DSApplication.java:35)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:353)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:180)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:629)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:584)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1438)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1414)
Comment 1 Brian de Alwis CLA 2012-03-13 17:24:18 EDT
Created attachment 212600 [details]
Sample program demonstrating the issue

This is rather fascinating to debug.  I've attached a little minimalist RCP app that demonstrates the problem.  This app doesn't have a default perspective.

Run it once, and then quit.  Run it again, and notice the NPEs described in comment 0.

Basically, a Window advisor whose preWindowOpen() causes the perspective bar to shown causes the status bar MToolControl to be serialized out as toBeRendered=true regardless of the whether it has contents.  So this widget is rendered before MWindow has been bound to a WorkbenchWindow.

A "normal" E3 compat app has a WorkbenchWindow associated with the E4 MWindow as a side-effect of setting an MPart's context (see attachment ss-ide.txt).  Since a no-perspective window has no parts, this side-effect never occurs.
Comment 2 Brian de Alwis CLA 2012-03-13 17:25:20 EDT
Created attachment 212601 [details]
Stacktrace from the IDE before it renders the StatusLine

This is the stack trace from putting a breakpoint on WorkbenchWindow.setup().  This method is the primary place where a IWorkbenchWindow is associated with its corresponding MTrimmedWindow's context.  Note that the status line is rendered because an MPart has had its context set.
Comment 3 Brian de Alwis CLA 2012-03-13 17:26:04 EDT
Created attachment 212602 [details]
Stacktrace from an app with no perspectives

This is the stack trace from putting a breakpoint on StatusTrim#createStatusLine() at the point where it skips creating any controls if there's no corresponding WorkbenchWindow.  (I should point out here that there are *no* parts on-screen)
Comment 4 Brian de Alwis CLA 2012-03-13 17:30:29 EDT
I should add that if you quit the demo app with the Welcome screen open, the subsequent start works with no AIOOBE.  My guess is that the part is rendered before the StatusLine, and so the MWindow has been bound to the WorkbenchWindow by the time the StatusLine is rendered.
Comment 5 Brian de Alwis CLA 2012-03-13 20:53:29 EDT
I'm wondering if we shouldn't just associated WorkbenchWindows with the MWindows on startup rather than as a side-effect, perhaps in E4Workbench#createAndRunUI().  I'll try that tomorrow.
Comment 6 Paul Webster CLA 2012-03-13 21:17:49 EDT
(In reply to comment #5)
> I'm wondering if we shouldn't just associated WorkbenchWindows with the
> MWindows on startup rather than as a side-effect, perhaps in
> E4Workbench#createAndRunUI().  I'll try that tomorrow.

E4Workbench can't see WorkbenchWindow ... possibly in Workbench itself?

PW
Comment 7 Michael Rennie CLA 2012-04-23 16:33:24 EDT
*** Bug 377425 has been marked as a duplicate of this bug. ***
Comment 8 Matthias Villiger CLA 2012-05-02 08:39:46 EDT
this bug is becoming critical for SWT scout applications.
is there any plan by when this could be fixed?
Comment 9 Brian de Alwis CLA 2012-05-02 09:09:50 EDT
Matthias, is this actually having a functional impact on Scout? I've only seen cosmetic impacts to date.

I actually cooked up a patch last night that solves this bug and bug 366110.  There's one small tweak necessary. I'll attach it in a moment; if you could try it, we can get this in for RC1.

I saw this AIOOBE occur when starting the IDE last night, which I've never seen previously.
Comment 10 Matthias Villiger CLA 2012-05-02 09:14:34 EDT
Hi Brian,

Unfortunately this has functional impact because as soon as this Exception occurs some views of the perspective are not displayed which is of course not the desired behavior :)

This would be great! I will test it as soon as possible. Thanks a lot!
Comment 11 Brian de Alwis CLA 2012-05-02 09:59:48 EDT
Created attachment 214925 [details]
Patch to create WorkbenchWindow after MWindow has been realized

This patch causes a WorkbenchWindow to be automatically opened around a new MWindow when the MWindow's widget is set.

WorkbenchWindowConfigurer#setTitle() must update the model's label as the WBWRenderer#createWidget() sets the shell's title to the model's label, which occurs after the set-widget event has been processed.
Comment 12 Matthias Villiger CLA 2012-05-02 12:36:42 EDT
I tested your patch and with this modifications I did not get any AIOOBE anymore!
So for me this is working fine! If this could get in RC1 this would be perfect.

Thanks for the very fast solution!
Comment 13 Brian de Alwis CLA 2012-05-02 12:40:34 EDT
Thanks for verifying, Matthias.
Comment 14 Eric Moffatt CLA 2012-05-10 10:31:52 EDT
+1, thanks Brian.

When verifying this one please ensure that we aren't making two WBW's anytime...
Comment 15 Eric Moffatt CLA 2012-05-10 11:05:35 EDT
I'm seeing an NPE in WorkbenchPage#setPerspective on a restart with no perspectives open...

Caused by: java.lang.NullPointerException
	at org.eclipse.ui.internal.WorkbenchPage.setPerspective(WorkbenchPage.java:3621)
	at org.eclipse.ui.internal.WorkbenchWindow.setup(WorkbenchWindow.java:542)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

I'm not sure why we're even calling setPerspective if there isn't any open. Note also that the WorkbenchWindow we create is identifying the 'ResourcePerspective' in its constructor (as is the setPerspective call above).
Comment 16 Brian de Alwis CLA 2012-05-10 13:03:58 EDT
Created attachment 215417 [details]
Updated patch

(In reply to comment #15)
> I'm seeing an NPE in WorkbenchPage#setPerspective on a restart with no
> perspectives open...

Steps to repeat (from IRC):
1. Start a fresh IDE product
2. Close the Java perspective
3. Quit
4. Restart: should popup an NPE

But I see this same NPE without the patch :-)

That said, changing the patch from:

+  createWorkbenchWindow(getDefaultPageInput(), getPerspectiveRegistry()
+     .findPerspectiveWithId(getDefaultPerspectiveId()), window, false);

to

+  createWorkbenchWindow(getDefaultPageInput(), null, window, false);

clears that up.
Comment 17 Eric Moffatt CLA 2012-05-10 16:04:14 EDT
Just to keep track of what's going on the last fix suggested ends up with a fresh workspace ending up with *no* perspective open instead of the Java perspective...

We're still trying to figure out how to provide a safe fix for this but anything that regresses 4.2 is out...
Comment 18 Eric Moffatt CLA 2012-05-10 16:36:36 EDT
Brian, if I add the following code to StandardTrim#createStatusLine I seem to get something that works OK (at least as far as the IDE is concerned (I left in a line above / below my additions for context):

// wbw may be null if workspace is started with no open perspectives.
if (wbw == null) {
  // Create one assuming there's no defined perspective
  Workbench wb = (Workbench) PlatformUI.getWorkbench();
  wb.createWorkbenchWindow(wb.getDefaultPageInput(), null,
  modelService.getTopLevelWindowFor(toolControl), false);
  wbw = (WorkbenchWindow) context.get(IWorkbenchWindow.class);
}

if (wbw != null) {

The theory here is that if the 'wbw' is null here then we don't have any perspective open (actually it means we've rendered at least one view but hey..;-).

This way this code only fires under exceptional circumstances making it less likely to interfere with the regular (albeit questionable) ordering.
Comment 19 Brian de Alwis CLA 2012-05-11 09:30:08 EDT
Created attachment 215474 [details]
Alternative patch

Matthias, I've turned Eric's code snippet into the attached patch.  Could you please report back on whether it resolves the issues you're seeing with Scout?
Comment 20 Matthias Villiger CLA 2012-05-11 09:52:05 EDT
Hi Brian,

Yes, I can confirm that with this patch I don't get the exception anymore.

Thanks
matthias
Comment 21 Eric Moffatt CLA 2012-05-11 10:04:21 EDT
Matthias, the real question is whether this fixes the "functional impact" you mentioned in comment #10 ?
Comment 22 Eric Moffatt CLA 2012-05-11 10:16:42 EDT
Brian, could you please +1 this if you're satisfied with the patch ?
Comment 23 Brian de Alwis CLA 2012-05-11 10:25:38 EDT
I'm fine with the patch
Comment 24 Matthias Villiger CLA 2012-05-11 10:29:47 EDT
Yes of course. I am still testing the cases. At the moment I can only say that the exception seems not to be thrown again. As soon as all checks have been completed, I will let you know.

matthias
Comment 25 Eric Moffatt CLA 2012-05-11 10:43:20 EDT
Thanks, I'll wait until you get back before committing the fix...
Comment 26 Brian de Alwis CLA 2012-05-11 11:07:38 EDT
Try again to give +1 to the review.
Comment 27 Eric Moffatt CLA 2012-05-11 11:31:30 EDT
Thanks Brian !

commit bf34877735a3f25e9afa1ab0330960641accca1d

Implement the code in comment #18 along with replacing the 'assert' in teh ToolControlRenderer with actual code to ensure that the AIOOB won't fire.

Matthias, if this does *not* fix the tests feel free to re-open and take another look (may mean that we slip into 4.2.1 though).
Comment 28 Matthias Villiger CLA 2012-05-14 10:08:47 EDT
I have completed the tests and can confirm that our SWT clients now work as expected! So the fix solves our issues.

Thanks a lot!
Matthias
Comment 29 Eric Moffatt CLA 2012-05-14 13:53:16 EDT
Verified in I20120513-1300.