JDK-5048370 : Disposing of Modal Dialogs can cause them to lose their Modality
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.2
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2004-05-17
  • Updated: 2005-12-01
  • Resolved: 2005-09-17
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6
6 b53Fixed
Related Reports
Relates :  
Description
Name: gm110360			Date: 05/17/2004


FULL PRODUCT VERSION :
java version "1.4.2_03"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_03-b02)
Java HotSpot(TM) Client VM (build 1.4.2_03-b02, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
Calling dispose() on a modal dialog, and then making it visible again can cause the Dialogs modality to be lost (it doesn't happen all the time, so I would assume it is a race condition between 2 Threads)

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
compile and execute the code supplied.
Close the dialog rapidly, and watch the integer counter increase on std out.
After several closes, show() will stop blocking, and the counter will rapidly increase.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
show() should block until the dialog is closed.
ACTUAL -
show() blocks for the 1st few closes of the Dialog, but eventually the Dialog will lose its modality, and show() will stop blocking.

REPRODUCIBILITY :
This bug can be reproduced often.

---------- BEGIN SOURCE ----------
import javax.swing.*;
public class DialogBug
{
   public static void main(String [] args)
   {
      JDialog fred = new JDialog((JFrame)null, true);
      fred.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
      
      int i = 0;
      while(true)
      {
         System.out.println(i++);
         fred.show();
      }
   }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
a) do not dispose of components.. or

b) Only make AWT & Swing components visible through the event dispatch Thread.

EventQueue.invokeAndWait(new Runnable() { public void run(){ component.setVisible(true)}});

Neither of these solutions is realy practical however.
(Incident Review ID: 260455) 
======================================================================

Comments
EVALUATION The previous version of the fix doesn't cover all the cases, in particular, it fixes AWT Dialogs but leave Swing JDialogs erroneous. I have found two problems in Swing code that cause this bug. First, when JDialog's default close operation is set to DISPOSE_ON_CLOSE, two methods are called: setVisible(false) and dispose(). If the dialog is shown again after setVisible(false) and before dispose(), then it doesn't block the calling thread. The second problem is in shared owner frame used for all parentless Swing windows. It will be eliminated in Mustang b51 (see 6300062).
02-09-2005

SUGGESTED FIX The fix can be the following: introduce a flag that indicates that the current dialog is being disposed. If it is set, then no hideAndDisposeHandler() should be called from Dialog.hide() - as it will be invoked later from doDispose(). ###@###.### 2005-06-16 14:51:58 GMT
16-06-2005

EVALUATION Name: atR10251 Date: 05/18/2004 The problem is that sometimes when dialog is being disposed it gets out of <show> but continues to be visible. I.e. some thread race occures. Then in the cycle in the test when <show> gets called again it doesn't block current thread, because it returns due to dialog visibility. It's normal behaviour that it returns, but it's a bug that it's visible in that moment. I was able to reproduce the bug with early tiger builds (b10), but wasn't able to do it with current b50. So, the bug is rather for dragon. ###@###.### 2004-05-18 ====================================================================== There is really a thread race in the bug, but the previous evaluation is not correct totally. The situation is follows: when Dialog.doDispose() is called, is invokes Dialog.hide() and unblocks the main thread there. Then, two threads are alive: main thread, which is showing the next dialog in the cycle, and EDT, which is returning from Dialog.hide() to Dialog.doDispose(). If the next dialog is shown before EDT gets out of Dialog.doDispose(), then the main thread will be unblocked from that method. The problem here is that we have two places in Dialog class, that unblock the calling (main) thread: hide() and doDispose() - both of them invoke hideAndDisposeHandler(), which performs unblocking. In fact, the latter method is called twice for modal dialogs being disposed, and that should be corrected. ###@###.### 2005-06-16 14:51:58 GMT
16-06-2005