# 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); + } +}