|
Quick Lists
|
|
Bug ID:
|
4098525
|
|
Votes
|
3
|
|
Synopsis
|
showing Modal dialog from JPanel's paint/addNotify/doLayout causes deadlock
|
|
Category
|
java:classes_swing
|
|
Reported Against
|
1.1.5
|
|
Release Fixed
|
|
|
State
|
11-Closed,
Not a Defect,
bug
|
|
Priority:
|
4-Low
|
|
Related Bugs
|
|
|
Submit Date
|
10-DEC-1997
|
|
Description
|
I am attempting to display a modal dialog before my GUI appears, but when I know the GUI is on
it's way to being shown. I've tried using addNotify, doLayout, and paint (among other things). I
was successful using addNotify on JDK 1.1.4. I have not been able to get anything to work using 1.1.5.
This is a serious problem for my project.
There are a couple of problems.
1. If the class displaying the dialog is a subclass of Panel, the dialog will work if shown from
paint(), but not addNotify() or doLayout(). Displaying FileDialog rather than my Dialog subclass
works in all cases. What is FileDialog's secret?
2. If the class displaying the dialog is a subclass of JPanel, the dialog never works. In the case
of paint(), the button seems to work, but the dispose() of the dialog hangs. Using addNotify or
doLayout will hang. Again, FileDialog works in all cases.
I would like to have the calling object be a subclass of JPanel and override addNotify (which
did work with 1.1.4). Even if I get something to work I am concerned since I don't understand
why some cases work and others don't, and what broke in 1.1.5.
Here is some code which displays the problems, there is the main class (Tester) and a dialog
class. Commenting out different lines will show the different behaviors.
-----------------------------------------------------------------------
/*
If use Panel as superclass:
addNotify doLayout paint
myDialog no no yes
fileDialog yes yes yes
If use JPanel as superclass:
Using paint, buttons work, but dialog.dispose() hangs.
Using addNotify and doLayout, nothing works.
addNotify doLayout paint
myDialog no no no
fileDialog yes yes yes
*/
import java.awt.event.*;
import java.awt.*;
import java.util.*;
import com.sun.java.swing.*;
public class Tester
//extends Panel
extends JPanel
implements ActionListener
{
boolean addNotify = false, paint = false, doLayout = false;
FileDialog fileDialog;
MyDialog myDialog;
static JFrame frame;
boolean firstTime = true;
public Tester ()
throws Exception
{
super();
//---- Comment out all but one of the following 3 lines ---
//addNotify = true;
paint = true;
//doLayout = true;
if (addNotify)
add(new Label("Dialog displayed during addNotify."));
if (paint)
add(new Label("Dialog displayed during paint."));
if (doLayout)
add(new Label("Dialog displayed during doLayout."));
fileDialog = new FileDialog(frame);
myDialog = new MyDialog(frame);
Button button = new Button("dialog");
button.addActionListener(this);
add(button);
}
public void actionPerformed(ActionEvent event)
{
myDialog.show(); // this works here
}
void showDialogs()
{
fileDialog.show();
myDialog.show();
}
public void addNotify()
{
super.addNotify();
if (addNotify)
showDialogs();
}
public void paint(Graphics g)
{
super.paint(g);
if (paint && firstTime)
{
firstTime = false;
showDialogs();
}
}
public void doLayout()
{
super.doLayout();
if (doLayout && firstTime)
{
firstTime = false;
showDialogs();
}
}
public static void main(String args[])
throws Exception
{
WindowListener l = new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
};
frame = new JFrame ("Test");
frame.addWindowListener(l);
frame.getContentPane().setLayout(new BorderLayout());
Tester gui = new Tester();
frame.getContentPane().add("Center", gui);
frame.setSize(800, 600);
frame.pack();
frame.setVisible(true);
}
}
-----------------------------------------------------------------------
import java.awt.*;
import java.awt.event.*;
class MyDialog extends Dialog
implements ActionListener
{
MyDialog(Frame parent)
{
//super(parent, "My Dialog", false); // works
super(parent, "My Dialog", true); // doesn't
add(new Label("Press the button"));
Button okButton = new Button("OK");
okButton.addActionListener(this);
add(okButton);
pack();
}
public void actionPerformed(ActionEvent event)
{
System.out.println("In handler");
dispose();
System.out.println("After dispose");
}
}
(Review ID: 21742)
======================================================================
|
|
Work Around
|
N/A
|
|
Evaluation
|
[aim 1/8/97]
A thread dump shows a deadlock between "AWT-Modal" & "AWT-EventQueue-0"
threads. (thread dump below)
The reason this occurs with swing's JPanel and not with a regular
AWT Panel is because swing's JComponent paint() method will invoke
it's paintChildren method which acquires the AWT lock via getTreeLock().
So the thread that is in paintChildren ("AWT-EventQueue-0") has this
unified lock and then calls Dialog.show(), which then does a wait()
(for reasons I won't go into here) and starts up another thread,
"AWT-Modal", which then shows the dialog and inserts itself into the
Motif X thread queue processing. "AWT-Modal" (via a map event) then
calls MPanelPeer.makeCursorsVisible, which attempts to get the
treeLock. hence->deadlock! AWT-EventQueue-0 holds the treeLock and
is waiting on the AWT-Modal thread object, and AWT-Modal holds it's
lock and is waiting attempting to acquire treeLock.
"AWT-Finalizer" (TID:0xee70ca00, sys_thread_t:0xede91db8, state:CW) prio=9
java.lang.Object.wait(Object.java)
sun.awt.AWTFinalizer.run(AWTFinalizer.java:48)
"AWT-Modal" (TID:0xee70c890, sys_thread_t:0xedec1db8, state:MW) prio=5
sun.awt.motif.MPanelPeer.makeCursorsVisible(MPanelPeer.java:50)
sun.awt.motif.ModalThread.run(MDialogPeer.java:148)
"AWT-Dispatch-Proxy" (TID:0xee70ca38, sys_thread_t:0xedef1db8, state:MW) prio=5
java.awt.Container.getComponents(Container.java:138)
com.sun.java.swing.JComponent.rectangleIsObscured(JComponent.java:2356)
com.sun.java.swing.JComponent.paint(JComponent.java:536)
java.awt.Container.paint(Container.java:702)
com.sun.java.swing.JFrame.update(JFrame.java:172)
java.awt.Component.dispatchEventImpl(Component.java:1725)
java.awt.Container.dispatchEventImpl(Container.java:939)
java.awt.Window.dispatchEventImpl(Window.java:443)
java.awt.Component.dispatchEvent(Component.java:1704)
java.awt.EventDispatchThread.run(EventDispatchThread.java:63)
"AWT-Dispatch-Proxy" (TID:0xee70d0f0, sys_thread_t:0xedf21db8, state:MW) prio=5
java.awt.Component$NativeInLightFixer.componentMoved(Component.java:2863)
java.awt.AWTEventMulticaster.componentMoved(AWTEventMulticaster.java:115)
java.awt.Component.processComponentEvent(Component.java:2173)
java.awt.Component.processEvent(Component.java:2141)
java.awt.Container.processEvent(Container.java:894)
java.awt.Component.dispatchEventImpl(Component.java:1764)
java.awt.Container.dispatchEventImpl(Container.java:939)
java.awt.Component.dispatchEvent(Component.java:1704)
java.awt.EventDispatchThread.run(EventDispatchThread.java:63)
"TimerQueue" (TID:0xee70d048, sys_thread_t:0xedf51db8, state:CW) prio=4
com.sun.java.swing.TimerQueue.run(TimerQueue.java:235)
java.lang.Thread.run(Thread.java)
"Screen Updater" (TID:0xee70cd98, sys_thread_t:0xedf81db8, state:CW) prio=4
java.lang.Object.wait(Object.java)
sun.awt.ScreenUpdater.nextEntry(ScreenUpdater.java:78)
sun.awt.ScreenUpdater.run(ScreenUpdater.java:98)
"AWT-Motif" (TID:0xee706960, sys_thread_t:0xedfb1db8, state:CW) prio=5
java.lang.Thread.run(Thread.java)
"AWT-Input" (TID:0xee706980, sys_thread_t:0xedfe1db8, state:CW) prio=5
"AWT-EventQueue-0" (TID:0xee706998, sys_thread_t:0xee011db8, state:CW) prio=5
java.lang.Object.wait(Object.java)
sun.awt.motif.MDialogPeer.show(MDialogPeer.java:104)
java.awt.Dialog.show(Dialog.java:220)
Tester.showDialogs(Tester.java:64)
Tester.paint(Tester.java:79)
com.sun.java.swing.JComponent.paintChildren(JComponent.java:394)
com.sun.java.swing.JComponent.paint(JComponent.java:540)
com.sun.java.swing.JComponent.paintChildren(JComponent.java:394)
com.sun.java.swing.JComponent.paint(JComponent.java:540)
com.sun.java.swing.JLayeredPane.paint(JLayeredPane.java:393)
com.sun.java.swing.JComponent.paintChildren(JComponent.java:394)
com.sun.java.swing.JComponent.paint(JComponent.java:525)
java.awt.Container.paint(Container.java:702)
java.awt.Component.dispatchEventImpl(Component.java:1723)
java.awt.Container.dispatchEventImpl(Container.java:939)
java.awt.Window.dispatchEventImpl(Window.java:443)
java.awt.Component.dispatchEvent(Component.java:1704)
java.awt.EventDispatchThread.run(EventDispatchThread.java:63)
"Finalizer thread" (TID:0xee700220, sys_thread_t:0xee2c1db8, state:CW) prio=1
"Async Garbage Collector" (TID:0xee700268, sys_thread_t:0xee2f1db8, state:CW) prio=1
"Idle thread" (TID:0xee7002b0, sys_thread_t:0xee3c1db8, state:R) prio=0 *current thread*
"Clock" (TID:0xee700088, sys_thread_t:0xee3f1db8, state:CW) prio=12
"main" (TID:0xee7000b0, sys_thread_t:0x69420, state:CW) prio=5
Monitor Cache Dump:
xxxxx@xxxxx /EE746B18: owner "AWT-EventQueue-0" (0xee011db8, 3 entries)
Waiting to enter:
"AWT-Dispatch-Proxy" (0xedf21db8)
"AWT-Dispatch-Proxy" (0xedef1db8)
"AWT-Modal" (0xedec1db8)
xxxxx@xxxxx /EE765380: <unowned>
Waiting to be notified:
"Screen Updater" (0xedf81db8)
xxxxx@xxxxx /EE754558: <unowned>
Waiting to be notified:
"AWT-Input" (0xedfe1db8)
"AWT-Motif" (0xedfb1db8)
xxxxx@xxxxx /EE767340: <unowned>
Waiting to be notified:
"AWT-Finalizer" (0xede91db8)
<unknown key> (0xee2f1db8): <unowned>
Waiting to be notified:
"Async Garbage Collector" (0xee2f1db8)
xxxxx@xxxxx /EE765AF0: <unowned>
Waiting to be notified:
"TimerQueue" (0xedf51db8)
xxxxx@xxxxx /EE7678F0: owner "AWT-Modal" (0xedec1db8, 1 entry)
Waiting to be notified:
"AWT-EventQueue-0" (0xee011db8)
The program should *not* show the modal dialog from the paint() method!!
I suspect the program also deadlocks in the addNotify/doLayout cases because
it's likely that in jdk1.1.5, AWT was fixed to properly acquire the
treeLock during these methods.
(This program is a good example of why Swing has made the statement that
it's not multi-thread capable; see http://java.sun.com/products/jfc/swingdoc/threads.html for more details).
-----------
A program should never call show() on a modal dialog while holding the
AWT treelock (or really any other locks on the GUI components) because
be design, this call will block while holding the lock.
This isn't something we can fix.
xxxxx@xxxxx 1998-10-09
|
|
Comments
|
Submitted On 14-MAY-2000
seleyS
TimerQueue" (TID:0xee70d048, sys_thread_t:0xedf51db8, state:CW) prio=4
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|
|
|
 |