Mercurial > hg > release > icedtea7-forest-2.4 > jdk
changeset 7247:26522cc1beae
8025588: [macosx] Frozen AppKit thread in 7u40
Reviewed-by: anthony, art, serb
author | pchelko |
---|---|
date | Thu, 28 Nov 2013 10:33:52 +0400 |
parents | a41e6d94840b |
children | 59b9673236c2 |
files | src/macosx/classes/sun/lwawt/macosx/CInputMethod.java src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java src/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java src/share/classes/java/awt/EventQueue.java src/share/classes/java/awt/event/InvocationEvent.java src/share/classes/sun/awt/AWTAccessor.java |
diffstat | 7 files changed, 143 insertions(+), 36 deletions(-) [+] |
line wrap: on
line diff
--- a/src/macosx/classes/sun/lwawt/macosx/CInputMethod.java Wed Nov 27 11:20:48 2013 -0800 +++ b/src/macosx/classes/sun/lwawt/macosx/CInputMethod.java Thu Nov 28 10:33:52 2013 +0400 @@ -620,8 +620,7 @@ retString[0] = new String(selectedText); }} }, fAwtFocussedComponent); - } catch (InterruptedException ie) { ie.printStackTrace(); } - catch (InvocationTargetException ite) { ite.printStackTrace(); } + } catch (InvocationTargetException ite) { ite.printStackTrace(); } synchronized(retString) { return retString[0]; } } @@ -669,8 +668,7 @@ }} }, fAwtFocussedComponent); - } catch (InterruptedException ie) { ie.printStackTrace(); } - catch (InvocationTargetException ite) { ite.printStackTrace(); } + } catch (InvocationTargetException ite) { ite.printStackTrace(); } synchronized(returnValue) { return returnValue; } } @@ -695,8 +693,7 @@ returnValue[0] = fIMContext.getInsertPositionOffset(); }} }, fAwtFocussedComponent); - } catch (InterruptedException ie) { ie.printStackTrace(); } - catch (InvocationTargetException ite) { ite.printStackTrace(); } + } catch (InvocationTargetException ite) { ite.printStackTrace(); } returnValue[1] = fCurrentTextLength; synchronized(returnValue) { return returnValue; } @@ -743,8 +740,7 @@ } }} }, fAwtFocussedComponent); - } catch (InterruptedException ie) { ie.printStackTrace(); } - catch (InvocationTargetException ite) { ite.printStackTrace(); } + } catch (InvocationTargetException ite) { ite.printStackTrace(); } synchronized(rect) { return rect; } } @@ -764,8 +760,7 @@ insertPositionOffset[0] = fIMContext.getInsertPositionOffset(); }} }, fAwtFocussedComponent); - } catch (InterruptedException ie) { ie.printStackTrace(); } - catch (InvocationTargetException ite) { ite.printStackTrace(); } + } catch (InvocationTargetException ite) { ite.printStackTrace(); } // This bit of gymnastics ensures that the returned location is within the composed text. // If it falls outside that region, the input method will commit the text, which is inconsistent with native
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed Nov 27 11:20:48 2013 -0800 +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Thu Nov 28 10:33:52 2013 +0400 @@ -918,7 +918,7 @@ //Posting an empty to flush the EventQueue without blocking the main thread } }, target); - } catch (InterruptedException | InvocationTargetException e) { + } catch (InvocationTargetException e) { e.printStackTrace(); } }
--- a/src/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java Wed Nov 27 11:20:48 2013 -0800 +++ b/src/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java Thu Nov 28 10:33:52 2013 +0400 @@ -97,6 +97,6 @@ setVisible(true); } }, this); - } catch (InterruptedException | InvocationTargetException ex) {} + } catch (InvocationTargetException ex) {} } }
--- a/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Wed Nov 27 11:20:48 2013 -0800 +++ b/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Thu Nov 28 10:33:52 2013 +0400 @@ -518,22 +518,21 @@ // Any selector invoked using ThreadUtilities performOnMainThread will be processed in doAWTRunLoop // The InvocationEvent will call LWCToolkit.stopAWTRunLoop() when finished, which will stop our manual runloop // Does not dispatch native events while in the loop - public static void invokeAndWait(Runnable event, Component component) throws InterruptedException, InvocationTargetException { + public static void invokeAndWait(Runnable runnable, Component component) throws InvocationTargetException { final long mediator = createAWTRunLoopMediator(); - InvocationEvent invocationEvent = - new InvocationEvent(component != null ? component : Toolkit.getDefaultToolkit(), event) { - @Override - public void dispatch() { - try { - super.dispatch(); - } finally { - if (mediator != 0) { - stopAWTRunLoop(mediator); + InvocationEvent invocationEvent = AWTAccessor.getInvocationEventAccessor() + .createEvent(component != null ? component : Toolkit.getDefaultToolkit(), + runnable, + new Runnable() { + @Override + public void run() { + if (mediator != 0) { + stopAWTRunLoop(mediator); + } } - } - } - }; + }, + true); if (component != null) { AppContext appContext = SunToolkit.targetToAppContext(component);
--- a/src/share/classes/java/awt/EventQueue.java Wed Nov 27 11:20:48 2013 -0800 +++ b/src/share/classes/java/awt/EventQueue.java Thu Nov 28 10:33:52 2013 +0400 @@ -1139,6 +1139,10 @@ if (entry.event instanceof SentEvent) { ((SentEvent)entry.event).dispose(); } + if (entry.event instanceof InvocationEvent) { + AWTAccessor.getInvocationEventAccessor() + .dispose((InvocationEvent)entry.event); + } if (prev == null) { queues[i].head = entry.next; } else {
--- a/src/share/classes/java/awt/event/InvocationEvent.java Wed Nov 27 11:20:48 2013 -0800 +++ b/src/share/classes/java/awt/event/InvocationEvent.java Thu Nov 28 10:33:52 2013 +0400 @@ -25,6 +25,8 @@ package java.awt.event; +import sun.awt.AWTAccessor; + import java.awt.ActiveEvent; import java.awt.AWTEvent; @@ -56,6 +58,20 @@ */ public class InvocationEvent extends AWTEvent implements ActiveEvent { + static { + AWTAccessor.setInvocationEventAccessor(new AWTAccessor.InvocationEventAccessor() { + @Override + public void dispose(InvocationEvent invocationEvent) { + invocationEvent.finishedDispatching(false); + } + @Override + public InvocationEvent createEvent(Object source, Runnable runnable, Runnable listener, + boolean catchThrowables) { + return new InvocationEvent(source, runnable, listener, catchThrowables); + } + }); + } + /** * Marks the first integer id for the range of invocation event ids. */ @@ -82,7 +98,15 @@ * * @see #isDispatched */ - protected Object notifier; + protected volatile Object notifier; + + /** + * The (potentially null) Runnable whose run() method will be called + * immediately after the event was dispatched or disposed. + * + * @see #isDispatched + */ + private final Runnable listener; /** * Indicates whether the <code>run()</code> method of the <code>runnable</code> @@ -147,7 +171,7 @@ * @see #InvocationEvent(Object, Runnable, Object, boolean) */ public InvocationEvent(Object source, Runnable runnable) { - this(source, runnable, null, false); + this(source, INVOCATION_DEFAULT, runnable, null, null, false); } /** @@ -185,7 +209,39 @@ */ public InvocationEvent(Object source, Runnable runnable, Object notifier, boolean catchThrowables) { - this(source, INVOCATION_DEFAULT, runnable, notifier, catchThrowables); + this(source, INVOCATION_DEFAULT, runnable, notifier, null, catchThrowables); + } + + /** + * Constructs an <code>InvocationEvent</code> with the specified + * source which will execute the runnable's <code>run</code> + * method when dispatched. If listener is non-<code>null</code>, + * <code>listener.run()</code> will be called immediately after + * <code>run</code> has returned, thrown an exception or the event + * was disposed. + * <p>This method throws an <code>IllegalArgumentException</code> + * if <code>source</code> is <code>null</code>. + * + * @param source The <code>Object</code> that originated + * the event + * @param runnable The <code>Runnable</code> whose + * <code>run</code> method will be + * executed + * @param listener The <code>Runnable</code>Runnable whose + * <code>run()</code> method will be called + * after the {@code InvocationEvent} + * was dispatched or disposed + * @param catchThrowables Specifies whether <code>dispatch</code> + * should catch Throwable when executing + * the <code>Runnable</code>'s <code>run</code> + * method, or should instead propagate those + * Throwables to the EventDispatchThread's + * dispatch loop + * @throws IllegalArgumentException if <code>source</code> is null + */ + private InvocationEvent(Object source, Runnable runnable, Runnable listener, + boolean catchThrowables) { + this(source, INVOCATION_DEFAULT, runnable, null, listener, catchThrowables); } /** @@ -221,13 +277,18 @@ */ protected InvocationEvent(Object source, int id, Runnable runnable, Object notifier, boolean catchThrowables) { + this(source, id, runnable, notifier, null, catchThrowables); + } + + private InvocationEvent(Object source, int id, Runnable runnable, + Object notifier, Runnable listener, boolean catchThrowables) { super(source, id); this.runnable = runnable; this.notifier = notifier; + this.listener = listener; this.catchExceptions = catchThrowables; this.when = System.currentTimeMillis(); } - /** * 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,13 +312,7 @@ runnable.run(); } } finally { - dispatched = true; - - if (notifier != null) { - synchronized (notifier) { - notifier.notifyAll(); - } - } + finishedDispatching(true); } } @@ -331,6 +386,25 @@ } /** + * Called when the event was dispatched or disposed + * @param dispatched true if the event was dispatched + * false if the event was disposed + */ + private void finishedDispatching(boolean dispatched) { + this.dispatched = dispatched; + + if (notifier != null) { + synchronized (notifier) { + notifier.notifyAll(); + } + } + + if (listener != null) { + listener.run(); + } + } + + /** * Returns a parameter string identifying this event. * This method is useful for event-logging and for debugging. *
--- a/src/share/classes/sun/awt/AWTAccessor.java Wed Nov 27 11:20:48 2013 -0800 +++ b/src/share/classes/sun/awt/AWTAccessor.java Thu Nov 28 10:33:52 2013 +0400 @@ -29,6 +29,7 @@ import java.awt.KeyboardFocusManager; import java.awt.DefaultKeyboardFocusManager; import java.awt.event.InputEvent; +import java.awt.event.InvocationEvent; import java.awt.event.KeyEvent; import java.awt.geom.Point2D; @@ -690,6 +691,25 @@ } /* + * An accessor object for the InvocationEvent class + */ + public interface InvocationEventAccessor { + /** + * Disposes the InvocationEvent + */ + void dispose(InvocationEvent event); + + /** + * Creates an InvocationEvent with a completion listener - + * a Runnable whose run() method will be called immediately after + * the event is dispatched or disposed + */ + InvocationEvent createEvent(Object source, Runnable runnable, Runnable listener, + boolean catchThrowables); + } + + + /* * Accessor instances are initialized in the static initializers of * corresponding AWT classes by using setters defined below. */ @@ -716,6 +736,7 @@ private static TrayIconAccessor trayIconAccessor; private static DefaultKeyboardFocusManagerAccessor defaultKeyboardFocusManagerAccessor; private static SequencedEventAccessor sequencedEventAccessor; + private static InvocationEventAccessor invocationEventAccessor; /* * Set an accessor object for the java.awt.Component class. @@ -1110,4 +1131,18 @@ // (so not a single instance of the event has been created). return sequencedEventAccessor; } + + /* + * Get the accessor object for the java.awt.event.InvocationEvent class. + */ + public static void setInvocationEventAccessor(InvocationEventAccessor invocationEventAccessor) { + AWTAccessor.invocationEventAccessor = invocationEventAccessor; + } + + /* + * Set the accessor object for the java.awt.event.InvocationEvent class. + */ + public static InvocationEventAccessor getInvocationEventAccessor() { + return invocationEventAccessor; + } }