--- old/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java 2012-08-28 18:06:50.342617600 +0400 +++ new/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java 2012-08-28 18:06:49.453566800 +0400 @@ -544,7 +544,7 @@ SunToolkit.postEvent(appContext, invocationEvent); // 3746956 - flush events from PostEventQueue to prevent them from getting stuck and causing a deadlock - sun.awt.SunToolkitSubclass.flushPendingEvents(appContext); + SunToolkit.flushPendingEvents(appContext); } else { // This should be the equivalent to EventQueue.invokeAndWait ((LWCToolkit)Toolkit.getDefaultToolkit()).getSystemEventQueueForInvokeAndWait().postEvent(invocationEvent); @@ -569,7 +569,7 @@ SunToolkit.postEvent(appContext, invocationEvent); // 3746956 - flush events from PostEventQueue to prevent them from getting stuck and causing a deadlock - sun.awt.SunToolkitSubclass.flushPendingEvents(appContext); + SunToolkit.flushPendingEvents(appContext); } else { // This should be the equivalent to EventQueue.invokeAndWait ((LWCToolkit)Toolkit.getDefaultToolkit()).getSystemEventQueueForInvokeAndWait().postEvent(invocationEvent); --- old/src/share/classes/java/awt/EventQueue.java 2012-08-28 18:06:54.572859600 +0400 +++ new/src/share/classes/java/awt/EventQueue.java 2012-08-28 18:06:53.740812000 +0400 @@ -1031,6 +1031,10 @@ } final boolean detachDispatchThread(EventDispatchThread edt, boolean forceDetach) { + /* + * Minimize discard possibility for non-posted events + */ + SunToolkit.flushPendingEvents(); /* * 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 +1053,7 @@ * Fix for 4648733. Check both the associated java event * queue and the PostEventQueue. */ - if (!forceDetach && (peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) { + if (!forceDetach && (peekEvent() != null)) { return false; } dispatchThread = null; --- old/src/share/classes/sun/awt/SunToolkit.java 2012-08-28 18:06:58.768099600 +0400 +++ new/src/share/classes/sun/awt/SunToolkit.java 2012-08-28 18:06:57.852047200 +0400 @@ -544,40 +544,25 @@ postEvent(targetToAppContext(e.getSource()), pe); } - protected static final Lock flushLock = new ReentrantLock(); - private static boolean isFlushingPendingEvents = false; - /* * Flush any pending events which haven't been posted to the AWT * EventQueue yet. */ public static void flushPendingEvents() { - flushLock.lock(); - try { - // Don't call flushPendingEvents() recursively - if (!isFlushingPendingEvents) { - isFlushingPendingEvents = true; - AppContext appContext = AppContext.getAppContext(); - PostEventQueue postEventQueue = - (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY); - if (postEventQueue != null) { - postEventQueue.flush(); - } - } - } finally { - isFlushingPendingEvents = false; - flushLock.unlock(); - } + AppContext appContext = AppContext.getAppContext(); + flushPendingEvents(appContext); } - public static boolean isPostEventQueueEmpty() { - AppContext appContext = AppContext.getAppContext(); + /* + * Flush the PostEventQueue for the right AppContext. + * The default flushPendingEvents only flushes the thread-local context, + * which is not always correct, c.f. 3746956 + */ + public static void flushPendingEvents(AppContext appContext) { PostEventQueue postEventQueue = - (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY); + (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY); if (postEventQueue != null) { - return postEventQueue.noEvents(); - } else { - return true; + postEventQueue.flush(); } } @@ -2112,17 +2097,16 @@ private EventQueueItem queueTail = null; private final EventQueue eventQueue; - // For the case when queue is cleared but events are not posted - private volatile boolean isFlushing = false; + // For synchronization of flush() method call + private boolean isFlushing = false; + + // For elimination of recursion of flush() method call + private final ThreadLocal isThreadLocalFlushing = new ThreadLocal<>(); PostEventQueue(EventQueue eq) { eventQueue = eq; } - public synchronized boolean noEvents() { - return queueHead == null && !isFlushing; - } - /* * Continually post pending AWTEvents to the Java EventQueue. The method * is synchronized to ensure the flush is completed before a new event @@ -2133,21 +2117,37 @@ * potentially lead to deadlock */ public void flush() { - EventQueueItem tempQueue; - synchronized (this) { - tempQueue = queueHead; - queueHead = queueTail = null; - isFlushing = true; + Boolean b = isThreadLocalFlushing.get(); + if (b != null && b) { + return; } + + isThreadLocalFlushing.set(true); try { + EventQueueItem tempQueue; + synchronized (this) { + while (isFlushing) { + wait(); + } + isFlushing = (queueHead != null); + + tempQueue = queueHead; + queueHead = queueTail = null; + } while (tempQueue != null) { eventQueue.postEvent(tempQueue.event); tempQueue = tempQueue.next; } } + catch (InterruptedException e) { + } finally { - isFlushing = false; + synchronized (this) { + isFlushing = false; + notifyAll(); + } } + isThreadLocalFlushing.set(false); } /* --- old/src/macosx/classes/sun/awt/SunToolkitSubclass.java 2012-08-28 18:07:02.796330000 +0400 +++ /dev/null 2012-08-28 18:07:03.000000000 +0400 @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2011, 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; - -// This class exists only so we can flush the PostEventQueue for the right AppContext -// The default flushPendingEvents only flushes the thread-local context, which is wrong. -// c.f. 3746956 -public abstract class SunToolkitSubclass extends SunToolkit { - public static void flushPendingEvents(AppContext appContext) { - flushLock.lock(); - PostEventQueue postEventQueue = (PostEventQueue)appContext.get("PostEventQueue"); - if (postEventQueue != null) { - postEventQueue.flush(); - } - flushLock.unlock(); - } -}