6811219: Deadlock java AWT in XWarningWindow
authoranthony
Tue, 19 May 2009 12:15:18 +0400
changeset 2804 a947dcefc8cb
parent 2803 e0fa1a27f1c1
child 2805 9f18d7e66042
6811219: Deadlock java AWT in XWarningWindow Summary: The locking scheme has been re-architected, the code slightly refactored. Reviewed-by: art, dcherepanov
jdk/src/solaris/classes/sun/awt/X11/XWarningWindow.java
jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java
--- a/jdk/src/solaris/classes/sun/awt/X11/XWarningWindow.java	Mon May 18 12:39:58 2009 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWarningWindow.java	Tue May 19 12:15:18 2009 +0400
@@ -34,74 +34,68 @@
 import sun.awt.SunToolkit;
 
 class XWarningWindow extends XWindow {
-    private final static int showingDelay = 330;
-    private final static int hidingDelay = 2000;
+    private final static int SHOWING_DELAY = 330;
+    private final static int HIDING_DELAY = 2000;
 
     private final Window ownerWindow;
     private WeakReference<XWindowPeer> ownerPeer;
-
-    public final Window getOwnerWindow() {
-        return ownerWindow;
-    }
     private long parentWindow;
 
     private final static String OWNER = "OWNER";
-
-    private static XIconInfo[][] icons;
-
     private InfoWindow.Tooltip tooltip;
 
-    private static synchronized XIconInfo getSecurityIconInfo(int size, int num) {
-        if (icons == null) {
-            icons = new XIconInfo[4][3];
-            if (XlibWrapper.dataModel == 32) {
-                icons[0][0] = new XIconInfo(XAWTIcon32_security_icon_bw16_png.security_icon_bw16_png);
-                icons[0][1] = new XIconInfo(XAWTIcon32_security_icon_interim16_png.security_icon_interim16_png);
-                icons[0][2] = new XIconInfo(XAWTIcon32_security_icon_yellow16_png.security_icon_yellow16_png);
-                icons[1][0] = new XIconInfo(XAWTIcon32_security_icon_bw24_png.security_icon_bw24_png);
-                icons[1][1] = new XIconInfo(XAWTIcon32_security_icon_interim24_png.security_icon_interim24_png);
-                icons[1][2] = new XIconInfo(XAWTIcon32_security_icon_yellow24_png.security_icon_yellow24_png);
-                icons[2][0] = new XIconInfo(XAWTIcon32_security_icon_bw32_png.security_icon_bw32_png);
-                icons[2][1] = new XIconInfo(XAWTIcon32_security_icon_interim32_png.security_icon_interim32_png);
-                icons[2][2] = new XIconInfo(XAWTIcon32_security_icon_yellow32_png.security_icon_yellow32_png);
-                icons[3][0] = new XIconInfo(XAWTIcon32_security_icon_bw48_png.security_icon_bw48_png);
-                icons[3][1] = new XIconInfo(XAWTIcon32_security_icon_interim48_png.security_icon_interim48_png);
-                icons[3][2] = new XIconInfo(XAWTIcon32_security_icon_yellow48_png.security_icon_yellow48_png);
-            } else {
-                icons[0][0] = new XIconInfo(XAWTIcon64_security_icon_bw16_png.security_icon_bw16_png);
-                icons[0][1] = new XIconInfo(XAWTIcon64_security_icon_interim16_png.security_icon_interim16_png);
-                icons[0][2] = new XIconInfo(XAWTIcon64_security_icon_yellow16_png.security_icon_yellow16_png);
-                icons[1][0] = new XIconInfo(XAWTIcon64_security_icon_bw24_png.security_icon_bw24_png);
-                icons[1][1] = new XIconInfo(XAWTIcon64_security_icon_interim24_png.security_icon_interim24_png);
-                icons[1][2] = new XIconInfo(XAWTIcon64_security_icon_yellow24_png.security_icon_yellow24_png);
-                icons[2][0] = new XIconInfo(XAWTIcon64_security_icon_bw32_png.security_icon_bw32_png);
-                icons[2][1] = new XIconInfo(XAWTIcon64_security_icon_interim32_png.security_icon_interim32_png);
-                icons[2][2] = new XIconInfo(XAWTIcon64_security_icon_yellow32_png.security_icon_yellow32_png);
-                icons[3][0] = new XIconInfo(XAWTIcon64_security_icon_bw48_png.security_icon_bw48_png);
-                icons[3][1] = new XIconInfo(XAWTIcon64_security_icon_interim48_png.security_icon_interim48_png);
-                icons[3][2] = new XIconInfo(XAWTIcon64_security_icon_yellow48_png.security_icon_yellow48_png);
+    /**
+     * Animation stage.
+     */
+    private volatile int currentIcon = 0;
+
+    /* -1 - uninitialized.
+     * 0 - 16x16
+     * 1 - 24x24
+     * 2 - 32x32
+     * 3 - 48x48
+     */
+    private int currentSize = -1;
+    private static XIconInfo[][] icons;
+    private static XIconInfo getSecurityIconInfo(int size, int num) {
+        synchronized (XWarningWindow.class) {
+            if (icons == null) {
+                icons = new XIconInfo[4][3];
+                if (XlibWrapper.dataModel == 32) {
+                    icons[0][0] = new XIconInfo(XAWTIcon32_security_icon_bw16_png.security_icon_bw16_png);
+                    icons[0][1] = new XIconInfo(XAWTIcon32_security_icon_interim16_png.security_icon_interim16_png);
+                    icons[0][2] = new XIconInfo(XAWTIcon32_security_icon_yellow16_png.security_icon_yellow16_png);
+                    icons[1][0] = new XIconInfo(XAWTIcon32_security_icon_bw24_png.security_icon_bw24_png);
+                    icons[1][1] = new XIconInfo(XAWTIcon32_security_icon_interim24_png.security_icon_interim24_png);
+                    icons[1][2] = new XIconInfo(XAWTIcon32_security_icon_yellow24_png.security_icon_yellow24_png);
+                    icons[2][0] = new XIconInfo(XAWTIcon32_security_icon_bw32_png.security_icon_bw32_png);
+                    icons[2][1] = new XIconInfo(XAWTIcon32_security_icon_interim32_png.security_icon_interim32_png);
+                    icons[2][2] = new XIconInfo(XAWTIcon32_security_icon_yellow32_png.security_icon_yellow32_png);
+                    icons[3][0] = new XIconInfo(XAWTIcon32_security_icon_bw48_png.security_icon_bw48_png);
+                    icons[3][1] = new XIconInfo(XAWTIcon32_security_icon_interim48_png.security_icon_interim48_png);
+                    icons[3][2] = new XIconInfo(XAWTIcon32_security_icon_yellow48_png.security_icon_yellow48_png);
+                } else {
+                    icons[0][0] = new XIconInfo(XAWTIcon64_security_icon_bw16_png.security_icon_bw16_png);
+                    icons[0][1] = new XIconInfo(XAWTIcon64_security_icon_interim16_png.security_icon_interim16_png);
+                    icons[0][2] = new XIconInfo(XAWTIcon64_security_icon_yellow16_png.security_icon_yellow16_png);
+                    icons[1][0] = new XIconInfo(XAWTIcon64_security_icon_bw24_png.security_icon_bw24_png);
+                    icons[1][1] = new XIconInfo(XAWTIcon64_security_icon_interim24_png.security_icon_interim24_png);
+                    icons[1][2] = new XIconInfo(XAWTIcon64_security_icon_yellow24_png.security_icon_yellow24_png);
+                    icons[2][0] = new XIconInfo(XAWTIcon64_security_icon_bw32_png.security_icon_bw32_png);
+                    icons[2][1] = new XIconInfo(XAWTIcon64_security_icon_interim32_png.security_icon_interim32_png);
+                    icons[2][2] = new XIconInfo(XAWTIcon64_security_icon_yellow32_png.security_icon_yellow32_png);
+                    icons[3][0] = new XIconInfo(XAWTIcon64_security_icon_bw48_png.security_icon_bw48_png);
+                    icons[3][1] = new XIconInfo(XAWTIcon64_security_icon_interim48_png.security_icon_interim48_png);
+                    icons[3][2] = new XIconInfo(XAWTIcon64_security_icon_yellow48_png.security_icon_yellow48_png);
+                }
             }
         }
         final int sizeIndex = size % icons.length;
         return icons[sizeIndex][num % icons[sizeIndex].length];
     }
 
-    private volatile int currentIcon = 0;
-
-    /* -1 - uninitialized yet
-     * 0 - 16x16
-     * 1 - 24x24
-     * 2 - 32x32
-     * 3 - 48x48
-     */
-    private volatile int currentSize = -1;
-
-    /** Indicates whether the shape of the window must be updated
-     */
-    private volatile boolean sizeUpdated = true;
-
-    private synchronized boolean updateIconSize() {
-        int newSize = currentSize;
+    private void updateIconSize() {
+        int newSize = -1;
 
         if (ownerWindow != null) {
             Insets insets = ownerWindow.getInsets();
@@ -117,14 +111,32 @@
                 newSize = 3;
             }
         }
-        if (newSize != currentSize) {
-            currentSize = newSize;
-            sizeUpdated = true;
+        // Make sure we have a valid size
+        if (newSize == -1) {
+            newSize = 0;
         }
-        return sizeUpdated;
+
+        // Note: this is not the most wise solution to use awtLock here,
+        // this should have been sync'ed with the stateLock. However,
+        // the awtLock must be taken first (see XBaseWindow.getStateLock()),
+        // and we need the awtLock anyway to update the shape of the icon.
+        // So it's easier to use just one lock instead.
+        XToolkit.awtLock();
+        try {
+            if (newSize != currentSize) {
+                currentSize = newSize;
+                XIconInfo ico = getSecurityIconInfo(currentSize, 0);
+                XlibWrapper.SetBitmapShape(XToolkit.getDisplay(), getWindow(),
+                        ico.getWidth(), ico.getHeight(), ico.getIntData());
+                AWTAccessor.getWindowAccessor().setSecurityWarningSize(
+                        ownerWindow, ico.getWidth(), ico.getHeight());
+            }
+        } finally {
+            XToolkit.awtUnlock();
+        }
     }
 
-    private synchronized XIconInfo getSecurityIconInfo() {
+    private XIconInfo getSecurityIconInfo() {
         updateIconSize();
         return getSecurityIconInfo(currentSize, currentIcon);
     }
@@ -183,28 +195,6 @@
         }
     }
 
-    private void updateWarningWindowBounds() {
-        XWindowPeer peer = ownerPeer.get();
-        if (peer != null) {
-            synchronized (this) {
-                if (updateIconSize()) {
-                    XIconInfo ico = getSecurityIconInfo();
-                    XToolkit.awtLock();
-                    try {
-                        XlibWrapper.SetBitmapShape(XToolkit.getDisplay(), getWindow(),
-                                ico.getWidth(), ico.getHeight(), ico.getIntData());
-                    } finally {
-                        XToolkit.awtUnlock();
-                    }
-                    sizeUpdated = false;
-                    AWTAccessor.getWindowAccessor().setSecurityWarningSize(
-                            ownerWindow, ico.getWidth(), ico.getHeight());
-                }
-            }
-            peer.repositionSecurityWarning();
-        }
-    }
-
     /**
      * @param x,y,w,h coordinates of the untrusted window
      */
@@ -376,25 +366,22 @@
 
     private final Runnable showingTask = new Runnable() {
         public void run() {
-            new Thread() {
-                public void run() {
-                    if (!isVisible()) {
-                        xSetVisible(true);
-                        updateWarningWindowBounds();
-                    }
-                    repaint();
-                    if (currentIcon > 0) {
-                        currentIcon--;
-                        XToolkit.schedule(showingTask, showingDelay);
-                    }
-                }}.start();
+            if (!isVisible()) {
+                xSetVisible(true);
+                updateIconSize();
+                XWindowPeer peer = ownerPeer.get();
+                if (peer != null) {
+                    peer.repositionSecurityWarning();
+                }
+            }
+            repaint();
+            if (currentIcon > 0) {
+                currentIcon--;
+                XToolkit.schedule(showingTask, SHOWING_DELAY);
+            }
         }
     };
 
-    public void setSecurityWarningVisible(boolean visible) {
-        setSecurityWarningVisible(visible, true);
-    }
-
     public void setSecurityWarningVisible(boolean visible, boolean doSchedule) {
         if (visible) {
             XToolkit.remove(hidingTask);
@@ -416,7 +403,7 @@
                 return;
             }
             if (doSchedule) {
-                XToolkit.schedule(hidingTask, hidingDelay);
+                XToolkit.schedule(hidingTask, HIDING_DELAY);
             } else {
                 hidingTask.run();
             }
--- a/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java	Mon May 18 12:39:58 2009 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java	Tue May 19 12:15:18 2009 +0400
@@ -1108,7 +1108,7 @@
             }
         }
 
-        warningWindow.setSecurityWarningVisible(show);
+        warningWindow.setSecurityWarningVisible(show, true);
     }
 
     boolean isOverrideRedirect() {