7081670: Disposing an AppContext can lead to a spinning EventDispatchThread
authoranthony
Mon, 26 Sep 2011 17:59:52 +0400
changeset 10583 8bb208d39fb1
parent 10582 6bb9de67122a
child 10584 012dafac5b62
7081670: Disposing an AppContext can lead to a spinning EventDispatchThread Reviewed-by: art, anthony, dholmes Contributed-by: Clemens Eisserer <linuxhippy@gmail.com>
jdk/src/share/classes/java/awt/EventDispatchThread.java
jdk/src/share/classes/java/awt/EventQueue.java
--- a/jdk/src/share/classes/java/awt/EventDispatchThread.java	Mon Sep 26 17:37:08 2011 +0400
+++ b/jdk/src/share/classes/java/awt/EventDispatchThread.java	Mon Sep 26 17:59:52 2011 +0400
@@ -34,8 +34,10 @@
 import sun.security.action.GetPropertyAction;
 import sun.awt.AWTAutoShutdown;
 import sun.awt.SunToolkit;
+import sun.awt.AppContext;
 
-import java.util.Vector;
+import java.util.ArrayList;
+import java.util.List;
 import sun.util.logging.PlatformLogger;
 
 import sun.awt.dnd.SunDragSourceContextPeer;
@@ -66,11 +68,11 @@
 
     private EventQueue theQueue;
     private boolean doDispatch = true;
-    private boolean threadDeathCaught = false;
+    private volatile boolean shutdown = false;
 
     private static final int ANY_EVENT = -1;
 
-    private Vector<EventFilter> eventFilters = new Vector<EventFilter>();
+    private ArrayList<EventFilter> eventFilters = new ArrayList<EventFilter>();
 
     EventDispatchThread(ThreadGroup group, String name, EventQueue queue) {
         super(group, name);
@@ -84,6 +86,11 @@
         doDispatch = false;
     }
 
+    public void interrupt() {
+        shutdown = true;
+        super.interrupt();
+    }
+
     public void run() {
         while (true) {
             try {
@@ -93,8 +100,7 @@
                     }
                 });
             } finally {
-                EventQueue eq = getEventQueue();
-                if (eq.detachDispatchThread(this) || threadDeathCaught) {
+                if(getEventQueue().detachDispatchThread(this, shutdown)) {
                     break;
                 }
             }
@@ -124,10 +130,9 @@
     void pumpEventsForFilter(int id, Conditional cond, EventFilter filter) {
         addEventFilter(filter);
         doDispatch = true;
-        while (doDispatch && cond.evaluate()) {
-            if (isInterrupted() || !pumpOneEventForFilters(id)) {
-                doDispatch = false;
-            }
+        shutdown |= isInterrupted();
+        while (doDispatch && !shutdown && cond.evaluate()) {
+            pumpOneEventForFilters(id);
         }
         removeEventFilter(filter);
     }
@@ -163,7 +168,7 @@
         }
     }
 
-    boolean pumpOneEventForFilters(int id) {
+    void pumpOneEventForFilters(int id) {
         AWTEvent event = null;
         boolean eventOK = false;
         try {
@@ -212,24 +217,18 @@
             if (delegate != null) {
                 delegate.afterDispatch(event, handle);
             }
-
-            return true;
         }
         catch (ThreadDeath death) {
-            threadDeathCaught = true;
-            return false;
-
+            shutdown = true;
+            throw death;
         }
         catch (InterruptedException interruptedException) {
-            return false; // AppContext.dispose() interrupts all
-                          // Threads in the AppContext
-
+            shutdown = true; // AppContext.dispose() interrupts all
+                             // Threads in the AppContext
         }
         catch (Throwable e) {
             processException(e);
         }
-
-        return true;
     }
 
     private void processException(Throwable e) {
--- a/jdk/src/share/classes/java/awt/EventQueue.java	Mon Sep 26 17:37:08 2011 +0400
+++ b/jdk/src/share/classes/java/awt/EventQueue.java	Mon Sep 26 17:59:52 2011 +0400
@@ -47,6 +47,7 @@
 
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import java.security.AccessControlContext;
 import java.security.ProtectionDomain;
@@ -99,12 +100,7 @@
  * @since       1.1
  */
 public class EventQueue {
-
-    // From Thread.java
-    private static int threadInitNumber;
-    private static synchronized int nextThreadNum() {
-        return threadInitNumber++;
-    }
+    private static final AtomicInteger threadInitNumber = new AtomicInteger(0);
 
     private static final int LOW_PRIORITY = 0;
     private static final int NORM_PRIORITY = 1;
@@ -175,9 +171,9 @@
      * Non-zero if a thread is waiting in getNextEvent(int) for an event of
      * a particular ID to be posted to the queue.
      */
-    private int waitForID;
+    private volatile int waitForID;
 
-    private final String name = "AWT-EventQueue-" + nextThreadNum();
+    private final String name = "AWT-EventQueue-" + threadInitNumber.getAndIncrement();
 
     private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventQueue");
 
@@ -1030,7 +1026,7 @@
         }
     }
 
-    final boolean detachDispatchThread(EventDispatchThread edt) {
+    final boolean detachDispatchThread(EventDispatchThread edt, boolean forceDetach) {
         /*
          * This synchronized block is to secure that the event dispatch
          * thread won't die in the middle of posting a new event to the
@@ -1049,7 +1045,7 @@
                  * Fix for 4648733. Check both the associated java event
                  * queue and the PostEventQueue.
                  */
-                if ((peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) {
+                if (!forceDetach && (peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) {
                     return false;
                 }
                 dispatchThread = null;