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

Bug 309497

Summary: Dialogs opened with Method.invoke("open") cause UIThreadTerminatedError on page refresh
Product: [RT] RAP Reporter: Adrian Stefanescu <stefanescu.a>
Component: RWTAssignee: Project Inbox <rap-inbox>
Status: RESOLVED INVALID QA Contact:
Severity: critical    
Priority: P3    
Version: 1.2   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:
Attachments:
Description Flags
Controls demo patch none

Description Adrian Stefanescu CLA 2010-04-16 11:07:29 EDT
Build Identifier: 1.2

If a modal dialog is opened with the open() method called over invoke and the page is refreshed while the dialog is open it will cause a UIThreadTerminatedError and a "The context has been disposed." exception. The browser needs to be reopened as the session still remain active.


Reproducible: Always

Steps to Reproduce:
1.Create a class that extends Dialog
2.Retrieve the "open()" method an call it with Method.invoke. 
3.Refresh the page and the application crashes. Browser needs to be restarted
Comment 1 Adrian Stefanescu CLA 2010-04-16 11:11:27 EDT
Here is the example that can be used to reproduce this bug:

Dlg class:
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.swt.widgets.Shell;

public class Dlg extends Dialog
{
    public Dlg( Shell parentShell )
    {
        super( parentShell );         
    }   
}


Code that causes the error called from a select:

Dlg dlg = new Dlg( getSite().getShell() );                    
Method m = dlg.getClass().getMethod( "open", new Class[0] );
m.invoke( dlg);

On page refresh while the dialog is opened it causes the current session to break and the browser needs to be reopened to start a new session.

java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
Caused by: org.eclipse.rwt.internal.lifecycle.RWTLifeCycle$UIThreadTerminatedError
	at org.eclipse.rwt.internal.lifecycle.RWTLifeCycle.sleep(RWTLifeCycle.java:308)
	at org.eclipse.swt.widgets.Display.sleep(Display.java:790)
	at org.eclipse.jface.window.Window.runEventLoop(Window.java:837)
	at org.eclipse.jface.window.Window.open(Window.java:812)

and also this exception:
java.lang.IllegalStateException: The context has been disposed.
	at org.eclipse.rwt.internal.service.ServiceContext.checkState(ServiceContext.java:154)
	at org.eclipse.rwt.internal.service.ServiceContext.getStateInfo(ServiceContext.java:104)
	at org.eclipse.rwt.internal.service.ContextProvider.getStateInfo(ContextProvider.java:166)
	at org.eclipse.rwt.SessionSingletonBase.getInstance(SessionSingletonBase.java:84)
	at org.eclipse.ui.internal.Workbench.getInstance(Workbench.java:466)
	at org.eclipse.ui.internal.ExceptionHandler.handleException(ExceptionHandler.java:60)
	at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2489)
	at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2444)
	at org.eclipse.ui.internal.Workbench.access$5(Workbench.java:2295)
	at org.eclipse.ui.internal.Workbench$4.run(Workbench.java:514)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:497)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:157)
	at com.atoss.atc.web.core.Application.createUI(Application.java:18)
	at org.eclipse.rwt.internal.lifecycle.EntryPointManager.createUI(EntryPointManager.java:92)
	at org.eclipse.rwt.internal.lifecycle.RWTLifeCycle.createUI(RWTLifeCycle.java:231)
	at org.eclipse.rwt.internal.lifecycle.RWTLifeCycle$UIThreadController.run(RWTLifeCycle.java:119)
	at java.lang.Thread.run(Unknown Source)
Exception in thread "UIThread [8m0h4a3my6eo]" java.lang.IllegalStateException: The context has been disposed.
	at org.eclipse.rwt.internal.service.ServiceContext.checkState(ServiceContext.java:154)
	at org.eclipse.rwt.internal.service.ServiceContext.getRequest(ServiceContext.java:82)
	at org.eclipse.rwt.internal.service.ContextProvider.getRequest(ContextProvider.java:129)
	at org.eclipse.rwt.internal.service.ContextProvider.getSession(ContextProvider.java:148)
	at org.eclipse.rwt.internal.lifecycle.RWTLifeCycle.setShutdownAdapter(RWTLifeCycle.java:350)
	at org.eclipse.rwt.internal.lifecycle.RWTLifeCycle.access$0(RWTLifeCycle.java:347)
	at org.eclipse.rwt.internal.lifecycle.RWTLifeCycle$UIThreadController.run(RWTLifeCycle.java:133)
	at java.lang.Thread.run(Unknown Source)
Comment 2 Adrian Stefanescu CLA 2010-04-16 11:15:51 EDT
This does the same as the code that causes the error except this one works and the page gets refreshed.

Dlg dlg = new Dlg( getSite().getShell() );
dlg.open();

Ok, the real problem is when I try to run some dialogs stored in some jar files that need to be called with invoke but the example above causes the same problem. A modal dialog that is opened with "invoke"(direct or indirect to a method that later calls open) will cause that thread error on refresh.
Comment 3 Ivan Furnadjiev CLA 2010-04-26 05:13:27 EDT
Created attachment 166056 [details]
Controls demo patch

This patch opens LoginDialog in Controls Demo -> DialogTab with reflection. Use it to reproduce the bug. When the dialog is still open, browser reload leads to UIThreadTerminatedError thrown by RWTLifeCycle#switchThread().
Comment 4 Ivan Furnadjiev CLA 2010-04-26 07:35:41 EDT
In RAP it is vital for the application restart not to prevent the ThreadDeath exception from propagation. Add this code in catch clause of InvocationTargetException to survive the restart:
....
try {
	method.invoke(....);
} catch( InvocationTargetException e ) {
  if( e.getTargetException() instanceof ThreadDeath ) {
    throw ( ThreadDeath )e.getTargetException();
  }
}
....
Tested with RAP from CVS HEAD.