Bug 238256

Summary: Eclipse freezes when SWT_AWT bridge is used and a modal AWT dialog is shown during shutdown
Product: [Eclipse Project] Platform Reporter: Willem Verstraeten <willem.verstraeten>
Component: SWTAssignee: Silenio Quarti <Silenio_Quarti>
Status: NEW --- QA Contact:
Severity: normal    
Priority: P3 CC: steve_northover
Version: 3.3.2   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:
Attachments:
Description Flags
Eclipse plugin project to reproduce the scenario none

Description Willem Verstraeten CLA 2008-06-24 10:46:48 EDT
Created attachment 105709 [details]
Eclipse plugin project to reproduce the scenario

Build ID: Build id: M20080221-1800

Steps To Reproduce:
1. Show an eclipse view with an SWT_AWT bridge in it.
2. Add a workbenchlistener that shows a modal AWT dialog during preShutDown in an invokeAndWait runnable
3. Close Eclipse

Expected result:
The AWT dialog is shown, and when that is closed, eclipse shuts down.

Actual result:
The Eclipse application freezes, and after a little while a blank dialog (the AWT dialog) is shown. No further interaction is possible


More information:
JRE : 1.6.0_05

As long as the view containing the SWT_AWT bridge was never shown, the dialog works just fine. When the view was shown at least once (and even if it is closed afterwards), Eclipse freezes on shutdown.

This scenario is a simplified case of a real scenario we have at our company, where a 3rd-party legacy application (ie. not modifiable) is being integrated into eclipse that requests some user information on shutdown.

======================================================================
AWT stack trace at the moment of the freeze (retrieved with JConsole):

Name: AWT-EventQueue-0
State: RUNNABLE
Total blocked: 1  Total waited: 3

Stack trace: 
sun.awt.windows.WDialogPeer.showModal(Native Method)
sun.awt.windows.WDialogPeer.realShow(Unknown Source)
sun.awt.windows.WWindowPeer.show(Unknown Source)
java.awt.Dialog.conditionalShow(Unknown Source)
   - locked java.awt.Component$AWTTreeLock@1546c85
java.awt.Dialog.show(Unknown Source)
javax.swing.JOptionPane.showInputDialog(Unknown Source)
javax.swing.JOptionPane.showInputDialog(Unknown Source)
javax.swing.JOptionPane.showInputDialog(Unknown Source)
javax.swing.JOptionPane.showInputDialog(Unknown Source)
com.luciad.test.Startup$2.run(Startup.java:27)
java.awt.event.InvocationEvent.dispatch(Unknown Source)
java.awt.EventQueue.dispatchEvent(Unknown Source)
java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
java.awt.EventDispatchThread.pumpEvents(Unknown Source)
java.awt.EventDispatchThread.pumpEvents(Unknown Source)
java.awt.EventDispatchThread.run(Unknown Source)

======================================================================
SWT stack trace during freeze:

Name: main
State: WAITING on java.awt.EventQueue$1AWTInvocationLock@1a9192b
Total blocked: 7  Total waited: 9

Stack trace: 
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:485)
java.awt.EventQueue.invokeAndWait(Unknown Source)
com.luciad.test.Startup$1.preShutdown(Startup.java:25)
org.eclipse.ui.internal.Workbench$7.run(Workbench.java:706)
org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:37)
org.eclipse.core.runtime.Platform.run(Platform.java:857)
org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:46)
org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:199)
org.eclipse.ui.internal.Workbench.firePreShutdown(Workbench.java:704)
org.eclipse.ui.internal.Workbench.busyClose(Workbench.java:844)
org.eclipse.ui.internal.Workbench.access$15(Workbench.java:834)
org.eclipse.ui.internal.Workbench$22.run(Workbench.java:1078)
org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:67)
org.eclipse.ui.internal.Workbench.close(Workbench.java:1076)
org.eclipse.ui.internal.Workbench.close(Workbench.java:1048)
org.eclipse.ui.internal.WorkbenchWindow.busyClose(WorkbenchWindow.java:696)
org.eclipse.ui.internal.WorkbenchWindow.access$0(WorkbenchWindow.java:675)
org.eclipse.ui.internal.WorkbenchWindow$2.run(WorkbenchWindow.java:790)
org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:67)
org.eclipse.ui.internal.WorkbenchWindow.close(WorkbenchWindow.java:788)
org.eclipse.jface.window.Window.handleShellCloseEvent(Window.java:736)
org.eclipse.jface.window.Window$3.shellClosed(Window.java:682)
org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:91)
org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:66)
org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:938)
org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:962)
org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:947)
org.eclipse.swt.widgets.Decorations.closeWidget(Decorations.java:301)
org.eclipse.swt.widgets.Decorations.WM_CLOSE(Decorations.java:1621)
org.eclipse.swt.widgets.Control.windowProc(Control.java:3674)
org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:291)
org.eclipse.swt.widgets.Decorations.windowProc(Decorations.java:1554)
org.eclipse.swt.widgets.Shell.windowProc(Shell.java:1753)
org.eclipse.swt.widgets.Display.windowProc(Display.java:4351)
org.eclipse.swt.internal.win32.OS.DefWindowProcW(Native Method)
org.eclipse.swt.internal.win32.OS.DefWindowProc(OS.java:2260)
org.eclipse.swt.widgets.Shell.callWindowProc(Shell.java:456)
org.eclipse.swt.widgets.Control.windowProc(Control.java:3760)
org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:291)
org.eclipse.swt.widgets.Decorations.windowProc(Decorations.java:1554)
org.eclipse.swt.widgets.Shell.windowProc(Shell.java:1753)
org.eclipse.swt.widgets.Display.windowProc(Display.java:4351)
org.eclipse.swt.internal.win32.OS.DefWindowProcW(Native Method)
org.eclipse.swt.internal.win32.OS.DefWindowProc(OS.java:2260)
org.eclipse.swt.widgets.Shell.callWindowProc(Shell.java:456)
org.eclipse.swt.widgets.Control.windowProc(Control.java:3760)
org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:291)
org.eclipse.swt.widgets.Decorations.windowProc(Decorations.java:1554)
org.eclipse.swt.widgets.Shell.windowProc(Shell.java:1753)
org.eclipse.swt.widgets.Display.windowProc(Display.java:4351)
org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method)
org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:2265)
org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3291)
org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2389)
org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2353)
org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2219)
org.eclipse.ui.internal.Workbench$4.run(Workbench.java:466)
org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:289)
org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:461)
org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:106)
org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:169)
org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:106)
org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:76)
org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:363)
org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:176)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:508)
org.eclipse.equinox.launcher.Main.basicRun(Main.java:447)
org.eclipse.equinox.launcher.Main.run(Main.java:1173)
org.eclipse.equinox.launcher.Main.main(Main.java:1148)
======================================================================
Comment 1 Steve Northover CLA 2008-06-24 10:53:57 EDT
Not sure there is much we can do about this.  I'm guessing that WDialogPeer.showModal() is sending a cross thread WM_ message and Eclipse is waiting on a lock and not running the event loop which would allow the cross thread message from AWT to be processed.
Comment 2 Willem Verstraeten CLA 2008-06-24 11:16:42 EDT
(In reply to comment #1)
> Not sure there is much we can do about this.  I'm guessing that
> WDialogPeer.showModal() is sending a cross thread WM_ message and Eclipse is
> waiting on a lock and not running the event loop which would allow the cross
> thread message from AWT to be processed.
> 

Does this mean that it is a bug in Sun's AWT implementation? Ie. do you think there is something that they can do to prevent this deadlock? Because not being able to show a modal dialog during Eclipse shutdown actually prevents the integration of our application in Eclipse.

Btw. I've tried showing the modal dialog outside of an invokeAndWait (ie. just inside the SWT thread) but this didn't work either.
Comment 3 Silenio Quarti CLA 2008-06-25 10:44:45 EDT
Calling invokeAndWait() or syncExec() will most certainly cause deadlocks. Are you able to change your code to something like this:


In com.luciad.test.Startup$1.preShutdown(Startup.java:25):

EventQueue.invokeLater(new Runnable() {
   public void run() {
      //code that shows the dialog;
   }
});
Display display = the SWT display
while (dialogIsUp()) {
    if (!display.readAndDispatch()) display.sleep()
}
Comment 4 Willem Verstraeten CLA 2008-06-25 11:40:32 EDT
With that workaround I managed to get it working, thanks !

By the way, as an alternative way of integrating SWT and AWT, we were trying to pump both event queues on the same thread (the AWT-EventQueue thread). We actually managed to get pretty far for stand-alone SWT applications. In the Eclipse workbench however the readAndDispatch loop is locked locked somewhere in a private method so not readily available, so we didn't manage to make it work for an Eclipse application (yet). I'll try to post the code later this week so you guys can tell if it's a good idea or not :)
Comment 5 Eclipse Webmaster CLA 2019-09-06 16:14:58 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.