7192977: Issue in toolkit thread
authorbagiras
Thu, 15 Nov 2012 23:03:31 +0400
changeset 16092 129d7d8a7399
parent 16091 4eb1062acb5b
child 16093 b305a8dc867f
7192977: Issue in toolkit thread Reviewed-by: skoivu, rupashka, art
jdk/src/share/classes/java/awt/EventQueue.java
jdk/src/share/classes/java/awt/Window.java
jdk/src/share/classes/javax/swing/RepaintManager.java
jdk/src/share/classes/sun/applet/AppletPanel.java
jdk/src/share/classes/sun/awt/AWTAccessor.java
jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java
jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java
--- a/jdk/src/share/classes/java/awt/EventQueue.java	Fri Nov 09 14:36:10 2012 -0800
+++ b/jdk/src/share/classes/java/awt/EventQueue.java	Thu Nov 15 23:03:31 2012 +0400
@@ -194,7 +194,8 @@
                 }
                 public void removeSourceEvents(EventQueue eventQueue,
                                                Object source,
-                                               boolean removeAllEvents) {
+                                               boolean removeAllEvents)
+                {
                     eventQueue.removeSourceEvents(source, removeAllEvents);
                 }
                 public boolean noEvents(EventQueue eventQueue) {
@@ -203,6 +204,11 @@
                 public void wakeup(EventQueue eventQueue, boolean isShutdown) {
                     eventQueue.wakeup(isShutdown);
                 }
+                public void invokeAndWait(Object source, Runnable r)
+                    throws InterruptedException, InvocationTargetException
+                {
+                    EventQueue.invokeAndWait(source, r);
+                }
             });
     }
 
@@ -1245,8 +1251,14 @@
      * @since           1.2
      */
     public static void invokeAndWait(Runnable runnable)
-             throws InterruptedException, InvocationTargetException {
+        throws InterruptedException, InvocationTargetException
+    {
+        invokeAndWait(Toolkit.getDefaultToolkit(), runnable);
+    }
 
+    static void invokeAndWait(Object source, Runnable runnable)
+        throws InterruptedException, InvocationTargetException
+    {
         if (EventQueue.isDispatchThread()) {
             throw new Error("Cannot call invokeAndWait from the event dispatcher thread");
         }
@@ -1255,8 +1267,7 @@
         Object lock = new AWTInvocationLock();
 
         InvocationEvent event =
-            new InvocationEvent(Toolkit.getDefaultToolkit(), runnable, lock,
-                                true);
+            new InvocationEvent(source, runnable, lock, true);
 
         synchronized (lock) {
             Toolkit.getEventQueue().postEvent(event);
--- a/jdk/src/share/classes/java/awt/Window.java	Fri Nov 09 14:36:10 2012 -0800
+++ b/jdk/src/share/classes/java/awt/Window.java	Thu Nov 15 23:03:31 2012 +0400
@@ -1206,7 +1206,7 @@
         }
         else {
             try {
-                EventQueue.invokeAndWait(action);
+                EventQueue.invokeAndWait(this, action);
             }
             catch (InterruptedException e) {
                 System.err.println("Disposal was interrupted:");
--- a/jdk/src/share/classes/javax/swing/RepaintManager.java	Fri Nov 09 14:36:10 2012 -0800
+++ b/jdk/src/share/classes/javax/swing/RepaintManager.java	Thu Nov 15 23:03:31 2012 +0400
@@ -27,11 +27,12 @@
 
 import java.awt.*;
 import java.awt.event.*;
-import java.awt.peer.ComponentPeer;
-import java.awt.peer.ContainerPeer;
 import java.awt.image.VolatileImage;
+import java.security.AccessControlContext;
 import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.applet.*;
 
 import sun.awt.AWTAccessor;
@@ -39,6 +40,8 @@
 import sun.awt.DisplayChangedListener;
 import sun.awt.SunToolkit;
 import sun.java2d.SunGraphicsEnvironment;
+import sun.misc.JavaSecurityAccess;
+import sun.misc.SharedSecrets;
 import sun.security.action.GetPropertyAction;
 
 import com.sun.java.swing.SwingUtilities3;
@@ -176,6 +179,9 @@
      */
     private final ProcessingRunnable processingRunnable;
 
+    private final static JavaSecurityAccess javaSecurityAccess =
+        SharedSecrets.getJavaSecurityAccess();
+
 
     static {
         volatileImageBufferEnabled = "true".equals(AccessController.
@@ -548,13 +554,26 @@
     // This is called from the toolkit thread when awt needs to run a
     // Runnable before we paint.
     //
-    void nativeQueueSurfaceDataRunnable(AppContext appContext, Component c,
-                                        Runnable r) {
+    void nativeQueueSurfaceDataRunnable(AppContext appContext,
+                                        final Component c, final Runnable r)
+    {
         synchronized(this) {
             if (runnableList == null) {
                 runnableList = new LinkedList<Runnable>();
             }
-            runnableList.add(r);
+            runnableList.add(new Runnable() {
+                public void run() {
+                    AccessControlContext stack = AccessController.getContext();
+                    AccessControlContext acc =
+                        AWTAccessor.getComponentAccessor().getAccessControlContext(c);
+                    javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Void>() {
+                        public Void run() {
+                            r.run();
+                            return null;
+                        }
+                    }, stack, acc);
+                }
+            });
         }
         scheduleProcessingRunnable(appContext);
     }
@@ -652,9 +671,9 @@
      * @see #addInvalidComponent
      */
     public void validateInvalidComponents() {
-        java.util.List<Component> ic;
+        final java.util.List<Component> ic;
         synchronized(this) {
-            if(invalidComponents == null) {
+            if (invalidComponents == null) {
                 return;
             }
             ic = invalidComponents;
@@ -662,7 +681,17 @@
         }
         int n = ic.size();
         for(int i = 0; i < n; i++) {
-            ic.get(i).validate();
+            final Component c = ic.get(i);
+            AccessControlContext stack = AccessController.getContext();
+            AccessControlContext acc =
+                AWTAccessor.getComponentAccessor().getAccessControlContext(c);
+            javaSecurityAccess.doIntersectionPrivilege(
+                new PrivilegedAction<Void>() {
+                    public Void run() {
+                        c.validate();
+                        return null;
+                    }
+                }, stack, acc);
         }
     }
 
@@ -740,78 +769,78 @@
         paintDirtyRegions(tmpDirtyComponents);
     }
 
-    private void paintDirtyRegions(Map<Component,Rectangle>
-                                   tmpDirtyComponents){
-        int i, count;
-        java.util.List<Component> roots;
-        Component dirtyComponent;
-
-        count = tmpDirtyComponents.size();
-        if (count == 0) {
+    private void paintDirtyRegions(
+        final Map<Component,Rectangle> tmpDirtyComponents)
+    {
+        if (tmpDirtyComponents.isEmpty()) {
             return;
         }
 
-        Rectangle rect;
-        int localBoundsX = 0;
-        int localBoundsY = 0;
-        int localBoundsH;
-        int localBoundsW;
-
-        roots = new ArrayList<Component>(count);
-
+        final java.util.List<Component> roots =
+            new ArrayList<Component>(tmpDirtyComponents.size());
         for (Component dirty : tmpDirtyComponents.keySet()) {
             collectDirtyComponents(tmpDirtyComponents, dirty, roots);
         }
 
-        count = roots.size();
+        final AtomicInteger count = new AtomicInteger(roots.size());
         painting = true;
         try {
-            for(i=0 ; i < count ; i++) {
-                dirtyComponent = roots.get(i);
-                rect = tmpDirtyComponents.get(dirtyComponent);
-                // Sometimes when RepaintManager is changed during the painting
-                // we may get null here, see #6995769 for details
-                if (rect == null) {
-                    continue;
-                }
-                localBoundsH = dirtyComponent.getHeight();
-                localBoundsW = dirtyComponent.getWidth();
+            for (int j=0 ; j < count.get(); j++) {
+                final int i = j;
+                final Component dirtyComponent = roots.get(j);
+                AccessControlContext stack = AccessController.getContext();
+                AccessControlContext acc =
+                    AWTAccessor.getComponentAccessor().getAccessControlContext(dirtyComponent);
+                javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Void>() {
+                    public Void run() {
+                        Rectangle rect = tmpDirtyComponents.get(dirtyComponent);
+                        // Sometimes when RepaintManager is changed during the painting
+                        // we may get null here, see #6995769 for details
+                        if (rect == null) {
+                            return null;
+                        }
 
-                SwingUtilities.computeIntersection(localBoundsX,
-                                                   localBoundsY,
-                                                   localBoundsW,
-                                                   localBoundsH,
-                                                   rect);
-                if (dirtyComponent instanceof JComponent) {
-                    ((JComponent)dirtyComponent).paintImmediately(
-                        rect.x,rect.y,rect.width, rect.height);
-                }
-                else if (dirtyComponent.isShowing()) {
-                    Graphics g = JComponent.safelyGetGraphics(
-                            dirtyComponent, dirtyComponent);
-                    // If the Graphics goes away, it means someone disposed of
-                    // the window, don't do anything.
-                    if (g != null) {
-                        g.setClip(rect.x, rect.y, rect.width, rect.height);
-                        try {
-                            dirtyComponent.paint(g);
-                        } finally {
-                            g.dispose();
+                        int localBoundsH = dirtyComponent.getHeight();
+                        int localBoundsW = dirtyComponent.getWidth();
+                        SwingUtilities.computeIntersection(0,
+                                                           0,
+                                                           localBoundsW,
+                                                           localBoundsH,
+                                                           rect);
+                        if (dirtyComponent instanceof JComponent) {
+                            ((JComponent)dirtyComponent).paintImmediately(
+                                rect.x,rect.y,rect.width, rect.height);
                         }
+                        else if (dirtyComponent.isShowing()) {
+                            Graphics g = JComponent.safelyGetGraphics(
+                                    dirtyComponent, dirtyComponent);
+                            // If the Graphics goes away, it means someone disposed of
+                            // the window, don't do anything.
+                            if (g != null) {
+                                g.setClip(rect.x, rect.y, rect.width, rect.height);
+                                try {
+                                    dirtyComponent.paint(g);
+                                } finally {
+                                    g.dispose();
+                                }
+                            }
+                        }
+                        // If the repaintRoot has been set, service it now and
+                        // remove any components that are children of repaintRoot.
+                        if (repaintRoot != null) {
+                            adjustRoots(repaintRoot, roots, i + 1);
+                            count.set(roots.size());
+                            paintManager.isRepaintingRoot = true;
+                            repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(),
+                                                         repaintRoot.getHeight());
+                            paintManager.isRepaintingRoot = false;
+                            // Only service repaintRoot once.
+                            repaintRoot = null;
+                        }
+
+                        return null;
                     }
-                }
-                // If the repaintRoot has been set, service it now and
-                // remove any components that are children of repaintRoot.
-                if (repaintRoot != null) {
-                    adjustRoots(repaintRoot, roots, i + 1);
-                    count = roots.size();
-                    paintManager.isRepaintingRoot = true;
-                    repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(),
-                                                 repaintRoot.getHeight());
-                    paintManager.isRepaintingRoot = false;
-                    // Only service repaintRoot once.
-                    repaintRoot = null;
-                }
+                }, stack, acc);
             }
         } finally {
             painting = false;
--- a/jdk/src/share/classes/sun/applet/AppletPanel.java	Fri Nov 09 14:36:10 2012 -0800
+++ b/jdk/src/share/classes/sun/applet/AppletPanel.java	Thu Nov 15 23:03:31 2012 +0400
@@ -45,6 +45,7 @@
 import java.util.Collections;
 import java.util.Locale;
 import java.util.WeakHashMap;
+import sun.awt.AWTAccessor;
 import sun.awt.AppContext;
 import sun.awt.EmbeddedFrame;
 import sun.awt.SunToolkit;
@@ -448,12 +449,12 @@
                       // to avoid deadlock.
                       try {
                           final AppletPanel p = this;
-
-                          EventQueue.invokeAndWait(new Runnable() {
-                                  public void run() {
-                                      p.validate();
-                                  }
-                              });
+                          Runnable r = new Runnable() {
+                              public void run() {
+                                  p.validate();
+                              }
+                          };
+                          AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
                       }
                       catch(InterruptedException ie) {
                       }
@@ -478,18 +479,19 @@
                       try {
                           final AppletPanel p = this;
                           final Applet a = applet;
-
-                          EventQueue.invokeAndWait(new Runnable() {
-                                  public void run() {
-                                      p.validate();
-                                      a.setVisible(true);
+                          Runnable r = new Runnable() {
+                              public void run() {
+                                  p.validate();
+                                  a.setVisible(true);
 
-                                      // Fix for BugTraq ID 4041703.
-                                      // Set the default focus for an applet.
-                                      if (hasInitialFocus())
-                                        setDefaultFocus();
+                                  // Fix for BugTraq ID 4041703.
+                                  // Set the default focus for an applet.
+                                  if (hasInitialFocus()) {
+                                      setDefaultFocus();
                                   }
-                              });
+                              }
+                          };
+                          AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
                       }
                       catch(InterruptedException ie) {
                       }
@@ -512,13 +514,12 @@
                     // to avoid deadlock.
                     try {
                         final Applet a = applet;
-
-                        EventQueue.invokeAndWait(new Runnable() {
-                                public void run()
-                                {
-                                    a.setVisible(false);
-                                }
-                            });
+                        Runnable r = new Runnable() {
+                            public void run() {
+                                a.setVisible(false);
+                            }
+                        };
+                        AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
                     }
                     catch(InterruptedException ie) {
                     }
@@ -570,17 +571,14 @@
                     }
                     status = APPLET_DISPOSE;
 
-                    try
-                    {
+                    try {
                         final Applet a = applet;
-
-                        EventQueue.invokeAndWait(new Runnable()
-                        {
-                            public void run()
-                            {
+                        Runnable r = new Runnable() {
+                            public void run() {
                                 remove(a);
                             }
-                        });
+                        };
+                        AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
                     }
                     catch(InterruptedException ie)
                     {
--- a/jdk/src/share/classes/sun/awt/AWTAccessor.java	Fri Nov 09 14:36:10 2012 -0800
+++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java	Thu Nov 15 23:03:31 2012 +0400
@@ -34,6 +34,8 @@
 import java.awt.event.KeyEvent;
 import java.awt.geom.Point2D;
 import java.awt.peer.ComponentPeer;
+
+import java.lang.reflect.InvocationTargetException;
 import java.security.AccessControlContext;
 
 import java.io.File;
@@ -476,6 +478,12 @@
          * appeared.
          */
         void wakeup(EventQueue eventQueue, boolean isShutdown);
+
+        /**
+         * Static in EventQueue
+         */
+        void invokeAndWait(Object source, Runnable r)
+            throws InterruptedException, InvocationTargetException;
     }
 
     /*
--- a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java	Fri Nov 09 14:36:10 2012 -0800
+++ b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java	Thu Nov 15 23:03:31 2012 +0400
@@ -488,14 +488,15 @@
                     try {
                         replaceSurfaceData();
                     } catch (InvalidPipeException e) {
-                    // REMIND : what do we do if our surface creation failed?
+                        // REMIND : what do we do if our surface creation failed?
                     }
                 }
             }
         };
+        Component c = (Component)target;
         // Fix 6255371.
-        if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing((Component)target, r)) {
-            postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), r));
+        if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing(c, r)) {
+            postEvent(new InvocationEvent(c, r));
         }
     }
 
@@ -618,7 +619,7 @@
     }
 
     public void disposeLater() {
-        postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), new Runnable() {
+        postEvent(new InvocationEvent(target, new Runnable() {
             public void run() {
                 dispose();
             }
--- a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java	Fri Nov 09 14:36:10 2012 -0800
+++ b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java	Thu Nov 15 23:03:31 2012 +0400
@@ -27,6 +27,7 @@
 
 import sun.awt.*;
 import java.awt.*;
+import java.awt.event.InvocationEvent;
 import java.awt.peer.ComponentPeer;
 import java.awt.image.*;
 import sun.awt.image.ByteInterleavedRaster;
@@ -232,11 +233,13 @@
         } else {
             // To avoid focus concurrence b/w IE and EmbeddedFrame
             // activation is postponed by means of posting it to EDT.
-            EventQueue.invokeLater(new Runnable() {
-                    public void run() {
-                        ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(true);
-                    }
-                });
+            Runnable r = new Runnable() {
+                public void run() {
+                    ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(true);
+                }
+            };
+            WToolkit.postEvent(WToolkit.targetToAppContext(this),
+                               new InvocationEvent(this, r));
         }
     }