7081670: Disposing an AppContext can lead to a spinning EventDispatchThread
Reviewed-by: art, anthony, dholmes
This commit is contained in:
parent
3cfef23dff
commit
20558b33b9
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user