6811219: Deadlock java AWT in XWarningWindow
authoranthony
Tue, 19 May 2009 12:15:18 +0400
changeset 1218875524a2b311
parent 1217 019fd945ebc5
child 1219 5eaa495dc929
6811219: Deadlock java AWT in XWarningWindow
Summary: The locking scheme has been re-architected, the code slightly refactored.
Reviewed-by: art, dcherepanov
src/solaris/classes/sun/awt/X11/XWarningWindow.java
src/solaris/classes/sun/awt/X11/XWindowPeer.java
     1.1 --- a/src/solaris/classes/sun/awt/X11/XWarningWindow.java	Mon May 18 12:39:58 2009 +0400
     1.2 +++ b/src/solaris/classes/sun/awt/X11/XWarningWindow.java	Tue May 19 12:15:18 2009 +0400
     1.3 @@ -34,74 +34,68 @@
     1.4  import sun.awt.SunToolkit;
     1.5  
     1.6  class XWarningWindow extends XWindow {
     1.7 -    private final static int showingDelay = 330;
     1.8 -    private final static int hidingDelay = 2000;
     1.9 +    private final static int SHOWING_DELAY = 330;
    1.10 +    private final static int HIDING_DELAY = 2000;
    1.11  
    1.12      private final Window ownerWindow;
    1.13      private WeakReference<XWindowPeer> ownerPeer;
    1.14 -
    1.15 -    public final Window getOwnerWindow() {
    1.16 -        return ownerWindow;
    1.17 -    }
    1.18      private long parentWindow;
    1.19  
    1.20      private final static String OWNER = "OWNER";
    1.21 -
    1.22 -    private static XIconInfo[][] icons;
    1.23 -
    1.24      private InfoWindow.Tooltip tooltip;
    1.25  
    1.26 -    private static synchronized XIconInfo getSecurityIconInfo(int size, int num) {
    1.27 -        if (icons == null) {
    1.28 -            icons = new XIconInfo[4][3];
    1.29 -            if (XlibWrapper.dataModel == 32) {
    1.30 -                icons[0][0] = new XIconInfo(XAWTIcon32_security_icon_bw16_png.security_icon_bw16_png);
    1.31 -                icons[0][1] = new XIconInfo(XAWTIcon32_security_icon_interim16_png.security_icon_interim16_png);
    1.32 -                icons[0][2] = new XIconInfo(XAWTIcon32_security_icon_yellow16_png.security_icon_yellow16_png);
    1.33 -                icons[1][0] = new XIconInfo(XAWTIcon32_security_icon_bw24_png.security_icon_bw24_png);
    1.34 -                icons[1][1] = new XIconInfo(XAWTIcon32_security_icon_interim24_png.security_icon_interim24_png);
    1.35 -                icons[1][2] = new XIconInfo(XAWTIcon32_security_icon_yellow24_png.security_icon_yellow24_png);
    1.36 -                icons[2][0] = new XIconInfo(XAWTIcon32_security_icon_bw32_png.security_icon_bw32_png);
    1.37 -                icons[2][1] = new XIconInfo(XAWTIcon32_security_icon_interim32_png.security_icon_interim32_png);
    1.38 -                icons[2][2] = new XIconInfo(XAWTIcon32_security_icon_yellow32_png.security_icon_yellow32_png);
    1.39 -                icons[3][0] = new XIconInfo(XAWTIcon32_security_icon_bw48_png.security_icon_bw48_png);
    1.40 -                icons[3][1] = new XIconInfo(XAWTIcon32_security_icon_interim48_png.security_icon_interim48_png);
    1.41 -                icons[3][2] = new XIconInfo(XAWTIcon32_security_icon_yellow48_png.security_icon_yellow48_png);
    1.42 -            } else {
    1.43 -                icons[0][0] = new XIconInfo(XAWTIcon64_security_icon_bw16_png.security_icon_bw16_png);
    1.44 -                icons[0][1] = new XIconInfo(XAWTIcon64_security_icon_interim16_png.security_icon_interim16_png);
    1.45 -                icons[0][2] = new XIconInfo(XAWTIcon64_security_icon_yellow16_png.security_icon_yellow16_png);
    1.46 -                icons[1][0] = new XIconInfo(XAWTIcon64_security_icon_bw24_png.security_icon_bw24_png);
    1.47 -                icons[1][1] = new XIconInfo(XAWTIcon64_security_icon_interim24_png.security_icon_interim24_png);
    1.48 -                icons[1][2] = new XIconInfo(XAWTIcon64_security_icon_yellow24_png.security_icon_yellow24_png);
    1.49 -                icons[2][0] = new XIconInfo(XAWTIcon64_security_icon_bw32_png.security_icon_bw32_png);
    1.50 -                icons[2][1] = new XIconInfo(XAWTIcon64_security_icon_interim32_png.security_icon_interim32_png);
    1.51 -                icons[2][2] = new XIconInfo(XAWTIcon64_security_icon_yellow32_png.security_icon_yellow32_png);
    1.52 -                icons[3][0] = new XIconInfo(XAWTIcon64_security_icon_bw48_png.security_icon_bw48_png);
    1.53 -                icons[3][1] = new XIconInfo(XAWTIcon64_security_icon_interim48_png.security_icon_interim48_png);
    1.54 -                icons[3][2] = new XIconInfo(XAWTIcon64_security_icon_yellow48_png.security_icon_yellow48_png);
    1.55 +    /**
    1.56 +     * Animation stage.
    1.57 +     */
    1.58 +    private volatile int currentIcon = 0;
    1.59 +
    1.60 +    /* -1 - uninitialized.
    1.61 +     * 0 - 16x16
    1.62 +     * 1 - 24x24
    1.63 +     * 2 - 32x32
    1.64 +     * 3 - 48x48
    1.65 +     */
    1.66 +    private int currentSize = -1;
    1.67 +    private static XIconInfo[][] icons;
    1.68 +    private static XIconInfo getSecurityIconInfo(int size, int num) {
    1.69 +        synchronized (XWarningWindow.class) {
    1.70 +            if (icons == null) {
    1.71 +                icons = new XIconInfo[4][3];
    1.72 +                if (XlibWrapper.dataModel == 32) {
    1.73 +                    icons[0][0] = new XIconInfo(XAWTIcon32_security_icon_bw16_png.security_icon_bw16_png);
    1.74 +                    icons[0][1] = new XIconInfo(XAWTIcon32_security_icon_interim16_png.security_icon_interim16_png);
    1.75 +                    icons[0][2] = new XIconInfo(XAWTIcon32_security_icon_yellow16_png.security_icon_yellow16_png);
    1.76 +                    icons[1][0] = new XIconInfo(XAWTIcon32_security_icon_bw24_png.security_icon_bw24_png);
    1.77 +                    icons[1][1] = new XIconInfo(XAWTIcon32_security_icon_interim24_png.security_icon_interim24_png);
    1.78 +                    icons[1][2] = new XIconInfo(XAWTIcon32_security_icon_yellow24_png.security_icon_yellow24_png);
    1.79 +                    icons[2][0] = new XIconInfo(XAWTIcon32_security_icon_bw32_png.security_icon_bw32_png);
    1.80 +                    icons[2][1] = new XIconInfo(XAWTIcon32_security_icon_interim32_png.security_icon_interim32_png);
    1.81 +                    icons[2][2] = new XIconInfo(XAWTIcon32_security_icon_yellow32_png.security_icon_yellow32_png);
    1.82 +                    icons[3][0] = new XIconInfo(XAWTIcon32_security_icon_bw48_png.security_icon_bw48_png);
    1.83 +                    icons[3][1] = new XIconInfo(XAWTIcon32_security_icon_interim48_png.security_icon_interim48_png);
    1.84 +                    icons[3][2] = new XIconInfo(XAWTIcon32_security_icon_yellow48_png.security_icon_yellow48_png);
    1.85 +                } else {
    1.86 +                    icons[0][0] = new XIconInfo(XAWTIcon64_security_icon_bw16_png.security_icon_bw16_png);
    1.87 +                    icons[0][1] = new XIconInfo(XAWTIcon64_security_icon_interim16_png.security_icon_interim16_png);
    1.88 +                    icons[0][2] = new XIconInfo(XAWTIcon64_security_icon_yellow16_png.security_icon_yellow16_png);
    1.89 +                    icons[1][0] = new XIconInfo(XAWTIcon64_security_icon_bw24_png.security_icon_bw24_png);
    1.90 +                    icons[1][1] = new XIconInfo(XAWTIcon64_security_icon_interim24_png.security_icon_interim24_png);
    1.91 +                    icons[1][2] = new XIconInfo(XAWTIcon64_security_icon_yellow24_png.security_icon_yellow24_png);
    1.92 +                    icons[2][0] = new XIconInfo(XAWTIcon64_security_icon_bw32_png.security_icon_bw32_png);
    1.93 +                    icons[2][1] = new XIconInfo(XAWTIcon64_security_icon_interim32_png.security_icon_interim32_png);
    1.94 +                    icons[2][2] = new XIconInfo(XAWTIcon64_security_icon_yellow32_png.security_icon_yellow32_png);
    1.95 +                    icons[3][0] = new XIconInfo(XAWTIcon64_security_icon_bw48_png.security_icon_bw48_png);
    1.96 +                    icons[3][1] = new XIconInfo(XAWTIcon64_security_icon_interim48_png.security_icon_interim48_png);
    1.97 +                    icons[3][2] = new XIconInfo(XAWTIcon64_security_icon_yellow48_png.security_icon_yellow48_png);
    1.98 +                }
    1.99              }
   1.100          }
   1.101          final int sizeIndex = size % icons.length;
   1.102          return icons[sizeIndex][num % icons[sizeIndex].length];
   1.103      }
   1.104  
   1.105 -    private volatile int currentIcon = 0;
   1.106 -
   1.107 -    /* -1 - uninitialized yet
   1.108 -     * 0 - 16x16
   1.109 -     * 1 - 24x24
   1.110 -     * 2 - 32x32
   1.111 -     * 3 - 48x48
   1.112 -     */
   1.113 -    private volatile int currentSize = -1;
   1.114 -
   1.115 -    /** Indicates whether the shape of the window must be updated
   1.116 -     */
   1.117 -    private volatile boolean sizeUpdated = true;
   1.118 -
   1.119 -    private synchronized boolean updateIconSize() {
   1.120 -        int newSize = currentSize;
   1.121 +    private void updateIconSize() {
   1.122 +        int newSize = -1;
   1.123  
   1.124          if (ownerWindow != null) {
   1.125              Insets insets = ownerWindow.getInsets();
   1.126 @@ -117,14 +111,32 @@
   1.127                  newSize = 3;
   1.128              }
   1.129          }
   1.130 -        if (newSize != currentSize) {
   1.131 -            currentSize = newSize;
   1.132 -            sizeUpdated = true;
   1.133 +        // Make sure we have a valid size
   1.134 +        if (newSize == -1) {
   1.135 +            newSize = 0;
   1.136          }
   1.137 -        return sizeUpdated;
   1.138 +
   1.139 +        // Note: this is not the most wise solution to use awtLock here,
   1.140 +        // this should have been sync'ed with the stateLock. However,
   1.141 +        // the awtLock must be taken first (see XBaseWindow.getStateLock()),
   1.142 +        // and we need the awtLock anyway to update the shape of the icon.
   1.143 +        // So it's easier to use just one lock instead.
   1.144 +        XToolkit.awtLock();
   1.145 +        try {
   1.146 +            if (newSize != currentSize) {
   1.147 +                currentSize = newSize;
   1.148 +                XIconInfo ico = getSecurityIconInfo(currentSize, 0);
   1.149 +                XlibWrapper.SetBitmapShape(XToolkit.getDisplay(), getWindow(),
   1.150 +                        ico.getWidth(), ico.getHeight(), ico.getIntData());
   1.151 +                AWTAccessor.getWindowAccessor().setSecurityWarningSize(
   1.152 +                        ownerWindow, ico.getWidth(), ico.getHeight());
   1.153 +            }
   1.154 +        } finally {
   1.155 +            XToolkit.awtUnlock();
   1.156 +        }
   1.157      }
   1.158  
   1.159 -    private synchronized XIconInfo getSecurityIconInfo() {
   1.160 +    private XIconInfo getSecurityIconInfo() {
   1.161          updateIconSize();
   1.162          return getSecurityIconInfo(currentSize, currentIcon);
   1.163      }
   1.164 @@ -183,28 +195,6 @@
   1.165          }
   1.166      }
   1.167  
   1.168 -    private void updateWarningWindowBounds() {
   1.169 -        XWindowPeer peer = ownerPeer.get();
   1.170 -        if (peer != null) {
   1.171 -            synchronized (this) {
   1.172 -                if (updateIconSize()) {
   1.173 -                    XIconInfo ico = getSecurityIconInfo();
   1.174 -                    XToolkit.awtLock();
   1.175 -                    try {
   1.176 -                        XlibWrapper.SetBitmapShape(XToolkit.getDisplay(), getWindow(),
   1.177 -                                ico.getWidth(), ico.getHeight(), ico.getIntData());
   1.178 -                    } finally {
   1.179 -                        XToolkit.awtUnlock();
   1.180 -                    }
   1.181 -                    sizeUpdated = false;
   1.182 -                    AWTAccessor.getWindowAccessor().setSecurityWarningSize(
   1.183 -                            ownerWindow, ico.getWidth(), ico.getHeight());
   1.184 -                }
   1.185 -            }
   1.186 -            peer.repositionSecurityWarning();
   1.187 -        }
   1.188 -    }
   1.189 -
   1.190      /**
   1.191       * @param x,y,w,h coordinates of the untrusted window
   1.192       */
   1.193 @@ -376,25 +366,22 @@
   1.194  
   1.195      private final Runnable showingTask = new Runnable() {
   1.196          public void run() {
   1.197 -            new Thread() {
   1.198 -                public void run() {
   1.199 -                    if (!isVisible()) {
   1.200 -                        xSetVisible(true);
   1.201 -                        updateWarningWindowBounds();
   1.202 -                    }
   1.203 -                    repaint();
   1.204 -                    if (currentIcon > 0) {
   1.205 -                        currentIcon--;
   1.206 -                        XToolkit.schedule(showingTask, showingDelay);
   1.207 -                    }
   1.208 -                }}.start();
   1.209 +            if (!isVisible()) {
   1.210 +                xSetVisible(true);
   1.211 +                updateIconSize();
   1.212 +                XWindowPeer peer = ownerPeer.get();
   1.213 +                if (peer != null) {
   1.214 +                    peer.repositionSecurityWarning();
   1.215 +                }
   1.216 +            }
   1.217 +            repaint();
   1.218 +            if (currentIcon > 0) {
   1.219 +                currentIcon--;
   1.220 +                XToolkit.schedule(showingTask, SHOWING_DELAY);
   1.221 +            }
   1.222          }
   1.223      };
   1.224  
   1.225 -    public void setSecurityWarningVisible(boolean visible) {
   1.226 -        setSecurityWarningVisible(visible, true);
   1.227 -    }
   1.228 -
   1.229      public void setSecurityWarningVisible(boolean visible, boolean doSchedule) {
   1.230          if (visible) {
   1.231              XToolkit.remove(hidingTask);
   1.232 @@ -416,7 +403,7 @@
   1.233                  return;
   1.234              }
   1.235              if (doSchedule) {
   1.236 -                XToolkit.schedule(hidingTask, hidingDelay);
   1.237 +                XToolkit.schedule(hidingTask, HIDING_DELAY);
   1.238              } else {
   1.239                  hidingTask.run();
   1.240              }
     2.1 --- a/src/solaris/classes/sun/awt/X11/XWindowPeer.java	Mon May 18 12:39:58 2009 +0400
     2.2 +++ b/src/solaris/classes/sun/awt/X11/XWindowPeer.java	Tue May 19 12:15:18 2009 +0400
     2.3 @@ -1108,7 +1108,7 @@
     2.4              }
     2.5          }
     2.6  
     2.7 -        warningWindow.setSecurityWarningVisible(show);
     2.8 +        warningWindow.setSecurityWarningVisible(show, true);
     2.9      }
    2.10  
    2.11      boolean isOverrideRedirect() {