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

Bug 362545

Summary: Workbench windows do not close with busy event queue
Product: [Eclipse Project] Platform Reporter: Marc R. Hoffmann <hoffmann>
Component: UIAssignee: Eric Moffatt <emoffatt>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: emoffatt, giachelini, pwebster, remy.suen
Version: 3.7.1Flags: pwebster: review+
Target Milestone: 3.7.2   
Hardware: PC   
OS: Windows 7   
Whiteboard:

Description Marc R. Hoffmann CLA 2011-11-01 03:38:43 EDT
Build Identifier: M20110909-1335

Since Eclipse 3.6.2 we have the problem, that workbench windows do not close any more in our RCP application.

BACKGROUND

The application is a multi-window RCP application used by Swiss Railroad (SBB) train dispatchers. Due to the asynchonous nature of the application events are constantly scheduled in the SWT event queue with asyncExec() to trigger repaints of graphical diagrams.

ANALYSIS

This is a regression that has been introduced with the fix for issue #333577:

http://dev.eclipse.org/viewcvs/viewvc.cgi/org.eclipse.ui.workbench/Eclipse%20UI/org/eclipse/ui/internal/WorkbenchWindow.java?r1=1.418&r2=1.418.2.1

In the method WorkbenchWindow.canHandleShellCloseEvent() the following code has been added:

    while (Display.getCurrent().readAndDispatch());

Obviously this will never return when the application is constantly dispatching asynchrounous events.



Reproducible: Always

Steps to Reproduce:
1. Have some RCP application the constanty uses Display.asyncExec() to update the user interface.
2. Open multiple workbench windows with this application (in our case > 10)
3. Click the window close frame decoration on one of the windows.

EXPECTED: The window closes
ACTUAL: The windows does not close
Comment 1 Paul Webster CLA 2011-11-03 15:27:42 EDT
This was trying to chew up SWT.Close events (at least that's what the comments say).

Eric, the brute force fix would be like adding a boolean to break out from the loop, set in an asyncExec(*) ... so that would be processed *after* any outstanding SWT OS events (like a pending SWT.Close).  Of course, that assumes I understand how display.readAndDispatch() works :-)

PW
Comment 2 Marc R. Hoffmann CLA 2011-11-30 03:21:15 EST
I propose the following fix: Instead of looping until the queue is empty from my understanding we simply need to wait until all events are processed, that were submitted before shellClosed() is called. If we schedule a simple sync command this should have exactly this effect.

My proposed fix is to replace the while loop in canHandleShellCloseEvent() with the following snippet:

// Wait until all pending 'Close' events are processes 
getWorkbench().getDisplay().syncExec(new Runnable() {
    public void run() {
    }
});

This fix works with the Windows 7 "Close Group" feature (I don't have access to XP right now to verify). It also solves the problem that the canHandleShellCloseEvent() hangs forever.

Is there any chance to get this fixed in 3.7.2? Unfortunately this issue is currently a complete show stopper for us.
Comment 3 Marc R. Hoffmann CLA 2011-12-12 03:04:50 EST
Can anybody retest my proposed fix? We urgently need this for 3.7.2.

Many thanks,
-marc
Comment 4 Eric Moffatt CLA 2011-12-15 14:51:53 EST
Paul and I were just discussing the fix for this and think that we've come up with a compromise that'll work...

Before we start running the loop we'll initiate an asynchExec that, when *it* runs  will force the exit of the loop. This has the advantage of purging any events that exist in the queue at the time we get called but not any ones that come in later.

I'll post the code snippet here once I have it...;-)
Comment 5 Marc R. Hoffmann CLA 2011-12-15 14:58:22 EST
Thanks great! As soon as you post the proposed fix we'll test it against our scenario.
Comment 6 Eric Moffatt CLA 2011-12-15 15:29:40 EST
Marc, here's the snippet we expect to contribute to 3.7.2...

final boolean[] boundingAsynchDone = { false };		Display.getCurrent().asyncExec(new Runnable() {
  public void run() {
     boundingAsynchDone[0] = true;
  }
});

// Ensure that any pending 'Close' event are flushed
// before opening any dialogs
while (!boundingAsynchDone[0] && Display.getCurrent().readAndDispatch())
			;
The theory is that this will allow the queue to purge but *only* until it hits the bounding asynch then closes (this should prevent us from endlessly spinning.

Could you please give this a try ? 

I re-tested the Close Groups scenario with the 'synchExec' snippet and it doesn't seem to work for those cases, perhaps this will cover both.
Comment 7 Marc R. Hoffmann CLA 2011-12-16 04:40:23 EST
Eric, the fix seems to works for our "busy queue" scenario. We will perform additional long-running tests over the weekend.

Many thanks!
Comment 8 Marc R. Hoffmann CLA 2011-12-19 03:38:36 EST
Eric, even our extended test scenarios did run successfully with your patch. Thanks!
Comment 9 Paul Webster CLA 2011-12-19 13:28:23 EST
Approved for 3.7.2

PW
Comment 11 Paul Webster CLA 2012-01-04 11:41:28 EST
.