Bug 517750 - Widget Disposed Error at Decorations.saveFocus
Summary: Widget Disposed Error at Decorations.saveFocus
Status: NEW
Alias: None
Product: RAP
Classification: RT
Component: Workbench (show other bugs)
Version: 3.1   Edit
Hardware: PC All
: P3 major (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords: needinfo
Depends on:
Blocks:
 
Reported: 2017-06-02 14:55 EDT by Kostiantyn Koval CLA
Modified: 2017-06-16 03:23 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Kostiantyn Koval CLA 2017-06-02 14:55:18 EDT
Bug 404020 didn't solve this issue.
When new Job is created and set to be user initiated then ProgressMonitorJobsDialog will be created internally. When I click on details button and stop currently running job the following things happen:

All the widgets disappear except the dialog. It becomes not close-able and application must be restarted. It happens in most of the cases. But sometimes it performs the task as expected. This suggests that one thread tries to access the disposed Toolbar (i found out that from debugging) and tries to get Shell which produces widget dispose error.

  final void saveFocus() {
    Control control = display.getFocusControl();
    if( control != null && control != this && this == control.getShell() ) {
      setSavedFocus( control );
    }
  }

LOG:
org.eclipse.swt.SWTException: Widget is disposed
at org.eclipse.swt.SWT.error(SWT.java:3708)
at org.eclipse.swt.SWT.error(SWT.java:3631)
at org.eclipse.swt.SWT.error(SWT.java:3602)
at org.eclipse.swt.widgets.Widget.error(Widget.java:1018)
at org.eclipse.swt.widgets.Widget.getDisplay(Widget.java:397)
at org.eclipse.swt.widgets.Widget.isValidThread(Widget.java:972)
at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:955)
at org.eclipse.swt.widgets.Control.getShell(Control.java:287)
at org.eclipse.swt.widgets.Decorations.saveFocus(Decorations.java:402)
at org.eclipse.swt.widgets.Display.setActiveShell(Display.java:857)
at org.eclipse.swt.widgets.Display.removeShell(Display.java:893)
at org.eclipse.swt.widgets.Shell.releaseParent(Shell.java:1015)
at org.eclipse.swt.widgets.Widget.dispose(Widget.java:848)
at org.eclipse.jface.window.Window.close(Window.java:353)
at org.eclipse.jface.dialogs.Dialog.close(Dialog.java:964)
at org.eclipse.jface.dialogs.ProgressMonitorDialog.close(ProgressMonitorDialog.java:369)
at org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog.close(ProgressMonitorJobsDialog.java:483)
at org.eclipse.ui.internal.progress.ProgressMonitorFocusJobDialog.close(ProgressMonitorFocusJobDialog.java:604)
at org.eclipse.jface.dialogs.ProgressMonitorDialog.finishedRun(ProgressMonitorDialog.java:618)
at org.eclipse.ui.internal.progress.ProgressMonitorFocusJobDialog.access$0(ProgressMonitorFocusJobDialog.java:1)
at org.eclipse.ui.internal.progress.ProgressMonitorFocusJobDialog$2$1$1.runInUIThread(ProgressMonitorFocusJobDialog.java:191)
at org.eclipse.ui.progress.UIJob$1.run(UIJob.java:102)
at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:38)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:193)
at org.eclipse.swt.widgets.Display.runPendingMessages(Display.java:1201)
at org.eclipse.swt.widgets.Display.safeReadAndDispatch(Display.java:1181)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:1173)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2733)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2694)
at org.eclipse.ui.internal.Workbench.access$5(Workbench.java:2530)
at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:701)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:336)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:684)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:157)


As a workaround I instantiate CustomDisplay (which is not recommended according to the documentation and I understand it is high risk class). The code is as follows:


final class DisplayCreator {


	static Display createDisplay() {

		//No display is attached to the current session.
		Assert.assertTrue(Display.getCurrent() == null);

		//Calling constructor registers this display withing this Session
		//as a result in future getCurrent should return instance of this display
		Display display = new CustomDisplay();

		//Complete normal creation (previously created display will be reused as it relies on Display.getCurrent())
		Display platformDisplay = PlatformUI.createDisplay();

		Assert.assertTrue(display.equals(platformDisplay));

		return display;
	}


	private static class CustomDisplay extends Display {
		@Override
		public Control getFocusControl() {
			Control focusControl = super.getFocusControl();

			if (focusControl != null && focusControl.isDisposed()) {
				return null;
			}
			return focusControl;
		}
	}
}


It would be nice if extra check would be placed in the if statement before calling getShell.
Thank you
Comment 1 Ivan Furnadjiev CLA 2017-06-05 06:37:27 EDT
Please provide a simple EntryPoint to reproduce the issue. Thanks.