JDK-6178755 : REGRESSION: JOptionPane's showInternal*Dialog methods never return
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 5.0
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2004-10-13
  • Updated: 2014-10-24
  • Resolved: 2011-05-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 7
7 b03Fixed
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode, sharing)

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

A DESCRIPTION OF THE PROBLEM :
JOptionPane's showInternal*Dialog methods never return.

When an Internal Dialog is displayed it blocks the current Thread until the Dialog is closed at which point the Thread resumes.  However I have an Internal Dialog being displayed from a Thread which isn't the Dispatch Thread and despite the OK button being pressed the Thread never resumes beyond the call to JOptionPane.showInternal***Dialog.

The problem seems to be in the java.awt.Container.startLWModal() method (lines 2633 -2639)

                while (windowClosingException == null) {
                    try {
                        getTreeLock().wait();
                    } catch (InterruptedException e) {
                        break;
                    }
                }

where wait() returns but windowClosingException is always null.  windowClosingException is set in two locations in java.awt.Component (lines 3933 and 4002)but only in response to a WindowClosing event not an Internal Frame closing.

As the Thread never resumes I am unable to process the User's input and proceed.  The example code provided works on JDK 1.4.1_05 and JDK 1.4.2, but not in JDK 1.5.0 beta 2, JDK 1.5.0 rc and JDK 1.5.0

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Use the example source code below.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Using the example code below:
System.out -> "Before showMessageDialog"
Message Dialog Appears
Click Message Dialog's OK button
Message Dialog Disappears
System.out-> "After showMessageDialog"
System.out -> "Before showInternalMessageDialog"
JDesktopPane containing Internal Message Dialog Appears
Click Internal Message Dialog's OK button
Internal Message Dialog Disappears
System.out -> After showInternalMessageDialog
JDesktopPane disappears
  Program exits
ACTUAL -
Using the example code below:
System.out -> "Before showMessageDialog"
Message Dialog Appears
Click Message Dialog's OK button
Message Dialog Disappears
System.out-> "After showMessageDialog"
System.out -> "Before showInternalMessageDialog"
JDesktopPane containing Internal Message Dialog Appears
Click Internal Message Dialog's OK button
Internal Message Dialog Disappears


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class OptionPaneTest
{
    public static void main( String[] args )
    {
        System.out.println( "Before showMessageDialog" );
        JOptionPane.showMessageDialog( null, "showMessageDialog" );
        System.out.println( "After showMessageDialog" );

        JDesktopPane desktopPane = new JDesktopPane();
        JFrame frame = new JFrame();
        frame.getContentPane().add( desktopPane );
        frame.setSize( 640, 480 );
        System.out.println( "Before showInternalMessageDialog" );
        JOptionPane.showInternalMessageDialog( desktopPane, "showInternalMessageDialog" );
        System.out.println( "After showInternalMessageDialog" );

        System.exit( 0 );
    }
}

---------- END SOURCE ----------

Release Regression From : 1.4.2_05
The above release value was the last known release where this 
bug was known to work. Since then there has been a regression.
###@###.### 10/13/04 21:34 GMT

Comments
EVALUATION The new bug about the deadlock is 6454631. It is added to the "See Also" list.
31-07-2006

EVALUATION I have noticed several more things. First is that the test provided for this bug is not completely correct: it shows internal JOptionPane from non-EDT (main) thread. As Swing is single-threaded toolkit, this is not allowed. Then, I'm not sure if this bug is a regression. I tried to run the test with 1.4.2 and 1.5.0, results are: with 1.5.0 behaviour is the same as with 1.6.0 (hang) and with 1.4.2 the calling thread successfully continues its execution, but the internal frame is not modal. A couple of words about the fix (see Suggested Fix for details). I tried it and it works fine, but at the same time it reveals another problem, another deadlock with AWT focuses. This deadlock has been in AWT for a long time (at least from 1.4.1) but with the fix for this bug it begins to happen more often. I will file that bug and update this CR with its number.
31-07-2006

EVALUATION Looking at the code in Container.startLWModal() and Container.stopLWModal() one can see the difference between two cases: when we start a new modal message pump from EDT and non-EDT thread. When we start the pump from EDT we just call to the function of EDT to process all the messages. When user closes the internal frame, we set a flag - Container.modalComp - to null and after that the function is returned and the calling thread (EDT) continues. As for non-EDT threads, we implement their blocking in another way. As in previous case we launch a new pump on EDT and then wait on the AWTTreeLock until ... - and here the bug is. Waiting condition is "windowClosingException == null", but the condition for message pump is "(windowClosingException == null) && (nativeContainer.modalComp != null)". This leads to the situation when we exit the messages pump but continue to wait and block the calling thread.
31-07-2006

SUGGESTED FIX *** /tmp/geta15899 2006-07-31 16:54:37.000000000 +0400 --- Container.java 2006-07-31 16:54:29.000000000 +0400 *************** *** 2648,2654 **** postEvent(new PeerEvent(this, pumpEventsForHierarchy, PeerEvent.PRIORITY_EVENT)); ! while (windowClosingException == null) { try { getTreeLock().wait(); } catch (InterruptedException e) { --- 2648,2654 ---- postEvent(new PeerEvent(this, pumpEventsForHierarchy, PeerEvent.PRIORITY_EVENT)); ! while ((windowClosingException == null) && (nativeContainer.modalComp != null)) { try { getTreeLock().wait(); } catch (InterruptedException e) {
31-07-2006

EVALUATION The contributed fix is for Container in AWT.
13-06-2006

EVALUATION Contribution forum : https://jdk-collaboration.dev.java.net/servlets/ProjectForumMessageView?forumID=1463&messageID=13392
08-06-2006

EVALUATION While we don't support doing Swing stuff on another thread, we should still try to be somewhat backward-compatible here. At the very least, we should avoid this failure of the method to return. ###@###.### 10/18/04 15:31 GMT
18-10-2004