# HG changeset patch
# User anthony
# Date 1342108821 -14400
# Node ID a51e0bc5a081bb75db4dbf158f5591ad770e55ca
# Parent 05c69338ee73c1e454aa632ced5cbc057420b404
7162144: Missing AWT thread in headless mode in 7u4 b06
Summary: invokeAndWait() will throw InterruptedException when the EDT.interrupt() is called
Reviewed-by: serb, bagiras
diff -r 05c69338ee73 -r a51e0bc5a081 src/share/classes/java/awt/EventQueue.java
--- a/src/share/classes/java/awt/EventQueue.java Thu Jul 12 14:47:13 2012 +0400
+++ b/src/share/classes/java/awt/EventQueue.java Thu Jul 12 20:00:21 2012 +0400
@@ -39,11 +39,12 @@
import sun.util.logging.PlatformLogger;
import sun.awt.AppContext;
+import sun.awt.AWTAccessor;
import sun.awt.AWTAutoShutdown;
+import sun.awt.AWTInterruptedException;
import sun.awt.PeerEvent;
import sun.awt.SunToolkit;
import sun.awt.EventQueueItem;
-import sun.awt.AWTAccessor;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
@@ -1038,15 +1039,17 @@
pushPopLock.lock();
try {
if (edt == dispatchThread) {
- /*
- * Don't detach the thread if any events are pending. Not
- * sure if it's a possible scenario, though.
- *
- * Fix for 4648733. Check both the associated java event
- * queue and the PostEventQueue.
- */
- if (!forceDetach && (peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) {
- return false;
+ if (peekEvent() != null || !SunToolkit.isPostEventQueueEmpty()) {
+ if (!forceDetach) {
+ /*
+ * Fix for 4648733. Check both the associated java event
+ * queue and the PostEventQueue.
+ */
+ return false;
+ } else {
+ // 7162144 - derail pending events
+ removeAllEvents();
+ }
}
dispatchThread = null;
}
@@ -1128,6 +1131,39 @@
}
}
+ private void removeAllEvents() {
+ SunToolkit.flushPendingEvents();
+ pushPopLock.lock();
+ try {
+ for (int i = 0; i < NUM_PRIORITIES; i++) {
+ EventQueueItem entry = queues[i].head;
+ EventQueueItem prev = null;
+ while (entry != null) {
+ if (entry.event instanceof InvocationEvent) {
+ AWTAccessor.getInvocationEventAccessor().
+ dispose((InvocationEvent)entry.event);
+ }
+ if (entry.event instanceof SequencedEvent) {
+ ((SequencedEvent)entry.event).dispose();
+ }
+ if (entry.event instanceof SentEvent) {
+ ((SentEvent)entry.event).dispose();
+ }
+ if (prev == null) {
+ queues[i].head = entry.next;
+ } else {
+ prev.next = entry.next;
+ }
+ uncacheEQItem(entry);
+ entry = entry.next;
+ }
+ queues[i].tail = prev;
+ }
+ } finally {
+ pushPopLock.unlock();
+ }
+ }
+
static void setCurrentEventAndMostRecentTime(AWTEvent e) {
Toolkit.getEventQueue().setCurrentEventAndMostRecentTimeImpl(e);
}
@@ -1235,7 +1271,11 @@
Throwable eventThrowable = event.getThrowable();
if (eventThrowable != null) {
- throw new InvocationTargetException(eventThrowable);
+ if (eventThrowable instanceof AWTInterruptedException) {
+ throw new InterruptedException(eventThrowable.getMessage());
+ } else {
+ throw new InvocationTargetException(eventThrowable);
+ }
}
}
diff -r 05c69338ee73 -r a51e0bc5a081 src/share/classes/java/awt/event/InvocationEvent.java
--- a/src/share/classes/java/awt/event/InvocationEvent.java Thu Jul 12 14:47:13 2012 +0400
+++ b/src/share/classes/java/awt/event/InvocationEvent.java Thu Jul 12 20:00:21 2012 +0400
@@ -28,6 +28,9 @@
import java.awt.ActiveEvent;
import java.awt.AWTEvent;
+import sun.awt.AWTAccessor;
+import sun.awt.AWTInterruptedException;
+
/**
* An event which executes the run()
method on a Runnable
*
when dispatched by the AWT event dispatcher thread. This class can
@@ -127,6 +130,16 @@
*/
private static final long serialVersionUID = 436056344909459450L;
+ static {
+ AWTAccessor.setInvocationEventAccessor(
+ new AWTAccessor.InvocationEventAccessor() {
+ @Override
+ public void dispose(InvocationEvent ie) {
+ ie.dispose();
+ }
+ });
+ }
+
/**
* Constructs an InvocationEvent
with the specified
* source which will execute the runnable's run
@@ -228,6 +241,19 @@
this.when = System.currentTimeMillis();
}
+ /*
+ * Marks the event as dispatched and notifies all interested parties.
+ */
+ private void setDispatched() {
+ dispatched = true;
+
+ if (notifier != null) {
+ synchronized (notifier) {
+ notifier.notifyAll();
+ }
+ }
+ }
+
/**
* Executes the Runnable's run()
method and notifies the
* notifier (if any) when run()
has returned or thrown an exception.
@@ -251,14 +277,16 @@
runnable.run();
}
} finally {
- dispatched = true;
+ setDispatched();
+ }
+ }
- if (notifier != null) {
- synchronized (notifier) {
- notifier.notifyAll();
- }
- }
- }
+ private void dispose() {
+ throwable = exception =
+ new AWTInterruptedException(
+ "The event is discarded due to Event Thread interruption");
+
+ setDispatched();
}
/**
diff -r 05c69338ee73 -r a51e0bc5a081 src/share/classes/sun/awt/AWTAccessor.java
--- a/src/share/classes/sun/awt/AWTAccessor.java Thu Jul 12 14:47:13 2012 +0400
+++ b/src/share/classes/sun/awt/AWTAccessor.java Thu Jul 12 20:00:21 2012 +0400
@@ -27,7 +27,7 @@
import java.awt.*;
import java.awt.KeyboardFocusManager;
-import java.awt.event.InputEvent;
+import java.awt.event.*;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
@@ -478,6 +478,16 @@
boolean isMultipleMode(FileDialog fileDialog);
}
+ /**
+ * An accessor for the InvocationEvent class
+ */
+ public interface InvocationEventAccessor {
+ /**
+ * Dispose an InvocationEvent (cancel it).
+ */
+ void dispose(InvocationEvent ie);
+ }
+
/*
* Accessor instances are initialized in the static initializers of
* corresponding AWT classes by using setters defined below.
@@ -493,6 +503,7 @@
private static EventQueueAccessor eventQueueAccessor;
private static PopupMenuAccessor popupMenuAccessor;
private static FileDialogAccessor fileDialogAccessor;
+ private static InvocationEventAccessor invocationEventAccessor;
/*
* Set an accessor object for the java.awt.Component class.
@@ -683,4 +694,21 @@
return fileDialogAccessor;
}
+ /**
+ * Set an accessor object for the java.awt.event.InvocationEvent class.
+ */
+ public static void setInvocationEventAccessor(InvocationEventAccessor iea) {
+ invocationEventAccessor = iea;
+ }
+
+ /**
+ * Retrieve the accessor object for the java.awt.event.InvocationEvent class.
+ */
+ public static InvocationEventAccessor getInvocationEventAccessor() {
+ if (invocationEventAccessor == null) {
+ unsafe.ensureClassInitialized(InvocationEvent.class);
+ }
+ return invocationEventAccessor;
+ }
+
}
diff -r 05c69338ee73 -r a51e0bc5a081 src/share/classes/sun/awt/AWTInterruptedException.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/awt/AWTInterruptedException.java Thu Jul 12 20:00:21 2012 +0400
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.awt;
+
+/**
+ * A utility exception class used to eliminate package borders between the
+ * EventQueue and the InvocationEvent classes.
+ */
+public class AWTInterruptedException extends Exception {
+ public AWTInterruptedException(String msg) {
+ super(msg);
+ }
+}