7081670: Disposing an AppContext can lead to a spinning EventDispatchThread
Reviewed-by: art, anthony, dholmes
Contributed-by: Clemens Eisserer <linuxhippy@gmail.com>
--- 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;