7081670: Disposing an AppContext can lead to a spinning EventDispatchThread

Reviewed-by: art, anthony, dholmes
This commit is contained in:
Clemens Eisserer 2011-09-26 17:59:52 +04:00 committed by Anthony Petrov
parent 3cfef23dff
commit 20558b33b9
2 changed files with 25 additions and 30 deletions

View File

@ -34,8 +34,10 @@ import java.security.AccessController;
import sun.security.action.GetPropertyAction; import sun.security.action.GetPropertyAction;
import sun.awt.AWTAutoShutdown; import sun.awt.AWTAutoShutdown;
import sun.awt.SunToolkit; 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.util.logging.PlatformLogger;
import sun.awt.dnd.SunDragSourceContextPeer; import sun.awt.dnd.SunDragSourceContextPeer;
@ -66,11 +68,11 @@ class EventDispatchThread extends Thread {
private EventQueue theQueue; private EventQueue theQueue;
private boolean doDispatch = true; private boolean doDispatch = true;
private boolean threadDeathCaught = false; private volatile boolean shutdown = false;
private static final int ANY_EVENT = -1; 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) { EventDispatchThread(ThreadGroup group, String name, EventQueue queue) {
super(group, name); super(group, name);
@ -84,6 +86,11 @@ class EventDispatchThread extends Thread {
doDispatch = false; doDispatch = false;
} }
public void interrupt() {
shutdown = true;
super.interrupt();
}
public void run() { public void run() {
while (true) { while (true) {
try { try {
@ -93,8 +100,7 @@ class EventDispatchThread extends Thread {
} }
}); });
} finally { } finally {
EventQueue eq = getEventQueue(); if(getEventQueue().detachDispatchThread(this, shutdown)) {
if (eq.detachDispatchThread(this) || threadDeathCaught) {
break; break;
} }
} }
@ -124,10 +130,9 @@ class EventDispatchThread extends Thread {
void pumpEventsForFilter(int id, Conditional cond, EventFilter filter) { void pumpEventsForFilter(int id, Conditional cond, EventFilter filter) {
addEventFilter(filter); addEventFilter(filter);
doDispatch = true; doDispatch = true;
while (doDispatch && cond.evaluate()) { shutdown |= isInterrupted();
if (isInterrupted() || !pumpOneEventForFilters(id)) { while (doDispatch && !shutdown && cond.evaluate()) {
doDispatch = false; pumpOneEventForFilters(id);
}
} }
removeEventFilter(filter); removeEventFilter(filter);
} }
@ -163,7 +168,7 @@ class EventDispatchThread extends Thread {
} }
} }
boolean pumpOneEventForFilters(int id) { void pumpOneEventForFilters(int id) {
AWTEvent event = null; AWTEvent event = null;
boolean eventOK = false; boolean eventOK = false;
try { try {
@ -212,24 +217,18 @@ class EventDispatchThread extends Thread {
if (delegate != null) { if (delegate != null) {
delegate.afterDispatch(event, handle); delegate.afterDispatch(event, handle);
} }
return true;
} }
catch (ThreadDeath death) { catch (ThreadDeath death) {
threadDeathCaught = true; shutdown = true;
return false; throw death;
} }
catch (InterruptedException interruptedException) { catch (InterruptedException interruptedException) {
return false; // AppContext.dispose() interrupts all shutdown = true; // AppContext.dispose() interrupts all
// Threads in the AppContext // Threads in the AppContext
} }
catch (Throwable e) { catch (Throwable e) {
processException(e); processException(e);
} }
return true;
} }
private void processException(Throwable e) { private void processException(Throwable e) {

View File

@ -47,6 +47,7 @@ import sun.awt.AWTAccessor;
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.atomic.AtomicInteger;
import java.security.AccessControlContext; import java.security.AccessControlContext;
import java.security.ProtectionDomain; import java.security.ProtectionDomain;
@ -99,12 +100,7 @@ import sun.misc.JavaSecurityAccess;
* @since 1.1 * @since 1.1
*/ */
public class EventQueue { public class EventQueue {
private static final AtomicInteger threadInitNumber = new AtomicInteger(0);
// From Thread.java
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
private static final int LOW_PRIORITY = 0; private static final int LOW_PRIORITY = 0;
private static final int NORM_PRIORITY = 1; private static final int NORM_PRIORITY = 1;
@ -175,9 +171,9 @@ public class EventQueue {
* Non-zero if a thread is waiting in getNextEvent(int) for an event of * Non-zero if a thread is waiting in getNextEvent(int) for an event of
* a particular ID to be posted to the queue. * 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"); private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventQueue");
@ -1030,7 +1026,7 @@ public class EventQueue {
} }
} }
final boolean detachDispatchThread(EventDispatchThread edt) { final boolean detachDispatchThread(EventDispatchThread edt, boolean forceDetach) {
/* /*
* This synchronized block is to secure that the event dispatch * This synchronized block is to secure that the event dispatch
* thread won't die in the middle of posting a new event to the * thread won't die in the middle of posting a new event to the
@ -1049,7 +1045,7 @@ public class EventQueue {
* Fix for 4648733. Check both the associated java event * Fix for 4648733. Check both the associated java event
* queue and the PostEventQueue. * queue and the PostEventQueue.
*/ */
if ((peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) { if (!forceDetach && (peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) {
return false; return false;
} }
dispatchThread = null; dispatchThread = null;