changeset 5500:a51e0bc5a081

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
author anthony
date Thu, 12 Jul 2012 20:00:21 +0400
parents 05c69338ee73
children c399756623cb
files src/share/classes/java/awt/EventQueue.java src/share/classes/java/awt/event/InvocationEvent.java src/share/classes/sun/awt/AWTAccessor.java src/share/classes/sun/awt/AWTInterruptedException.java
diffstat 4 files changed, 151 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- 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);
+            }
         }
     }
 
--- 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 <code>run()</code> method on a <code>Runnable
  * </code> 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 <code>InvocationEvent</code> with the specified
      * source which will execute the runnable's <code>run</code>
@@ -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 <code>run()</code> method and notifies the
      * notifier (if any) when <code>run()</code> 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();
     }
 
     /**
--- 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;
+    }
+
 }
--- /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);
+    }
+}