8025588: [macosx] Frozen AppKit thread in 7u40

Reviewed-by: anthony, art, serb
This commit is contained in:
Petr Pchelko 2013-10-10 11:40:06 +04:00
parent 1f3355acb3
commit dafa242f76
7 changed files with 127 additions and 36 deletions

View File

@ -620,8 +620,7 @@ public class CInputMethod extends InputMethodAdapter {
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 @@ public class CInputMethod extends InputMethodAdapter {
}}
}, fAwtFocussedComponent);
} catch (InterruptedException ie) { ie.printStackTrace(); }
catch (InvocationTargetException ite) { ite.printStackTrace(); }
} catch (InvocationTargetException ite) { ite.printStackTrace(); }
synchronized(returnValue) { return returnValue; }
}
@ -695,8 +693,7 @@ public class CInputMethod extends InputMethodAdapter {
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 @@ public class CInputMethod extends InputMethodAdapter {
}
}}
}, fAwtFocussedComponent);
} catch (InterruptedException ie) { ie.printStackTrace(); }
catch (InvocationTargetException ite) { ite.printStackTrace(); }
} catch (InvocationTargetException ite) { ite.printStackTrace(); }
synchronized(rect) { return rect; }
}
@ -764,8 +760,7 @@ public class CInputMethod extends InputMethodAdapter {
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

View File

@ -884,7 +884,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
//Posting an empty to flush the EventQueue without blocking the main thread
}
}, target);
} catch (InterruptedException | InvocationTargetException e) {
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}

View File

@ -97,6 +97,6 @@ public class CViewEmbeddedFrame extends EmbeddedFrame {
setVisible(true);
}
}, this);
} catch (InterruptedException | InvocationTargetException ex) {}
} catch (InvocationTargetException ex) {}
}
}

View File

@ -548,22 +548,18 @@ public final class LWCToolkit extends LWToolkit {
// 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 {
new InvocationEvent(component != null ? component : Toolkit.getDefaultToolkit(),
runnable,
() -> {
if (mediator != 0) {
stopAWTRunLoop(mediator);
}
}
}
};
},
true);
if (component != null) {
AppContext appContext = SunToolkit.targetToAppContext(component);

View File

@ -1159,6 +1159,10 @@ public class EventQueue {
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 {

View File

@ -25,6 +25,8 @@
package java.awt.event;
import sun.awt.AWTAccessor;
import java.awt.ActiveEvent;
import java.awt.AWTEvent;
@ -56,6 +58,15 @@ import java.awt.AWTEvent;
*/
public class InvocationEvent extends AWTEvent implements ActiveEvent {
static {
AWTAccessor.setInvocationEventAccessor(new AWTAccessor.InvocationEventAccessor() {
@Override
public void dispose(InvocationEvent invocationEvent) {
invocationEvent.finishedDispatching(false);
}
});
}
/**
* Marks the first integer id for the range of invocation event ids.
*/
@ -78,11 +89,21 @@ public class InvocationEvent extends AWTEvent implements ActiveEvent {
/**
* The (potentially null) Object whose notifyAll() method will be called
* immediately after the Runnable.run() method has returned or thrown an exception.
* immediately after the Runnable.run() method has returned or thrown an exception
* or after the event was disposed.
*
* @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
* @since 1.8
*/
private final Runnable listener;
/**
* Indicates whether the <code>run()</code> method of the <code>runnable</code>
@ -147,7 +168,7 @@ public class InvocationEvent extends AWTEvent implements ActiveEvent {
* @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);
}
/**
@ -171,7 +192,8 @@ public class InvocationEvent extends AWTEvent implements ActiveEvent {
* @param notifier The {@code Object} whose <code>notifyAll</code>
* method will be called after
* <code>Runnable.run</code> has returned or
* thrown an exception
* thrown an exception or after the event was
* disposed
* @param catchThrowables Specifies whether <code>dispatch</code>
* should catch Throwable when executing
* the <code>Runnable</code>'s <code>run</code>
@ -185,7 +207,39 @@ public class InvocationEvent extends AWTEvent implements ActiveEvent {
*/
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
*/
public InvocationEvent(Object source, Runnable runnable, Runnable listener,
boolean catchThrowables) {
this(source, INVOCATION_DEFAULT, runnable, null, listener, catchThrowables);
}
/**
@ -208,7 +262,8 @@ public class InvocationEvent extends AWTEvent implements ActiveEvent {
* @param notifier The <code>Object</code> whose <code>notifyAll</code>
* method will be called after
* <code>Runnable.run</code> has returned or
* thrown an exception
* thrown an exception or after the event was
* disposed
* @param catchThrowables Specifies whether <code>dispatch</code>
* should catch Throwable when executing the
* <code>Runnable</code>'s <code>run</code>
@ -221,13 +276,18 @@ public class InvocationEvent extends AWTEvent implements ActiveEvent {
*/
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 +311,7 @@ public class InvocationEvent extends AWTEvent implements ActiveEvent {
runnable.run();
}
} finally {
dispatched = true;
if (notifier != null) {
synchronized (notifier) {
notifier.notifyAll();
}
}
finishedDispatching(true);
}
}
@ -330,6 +384,25 @@ public class InvocationEvent extends AWTEvent implements ActiveEvent {
return dispatched;
}
/**
* 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.

View File

@ -31,6 +31,7 @@ import java.awt.*;
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;
import java.awt.peer.ComponentPeer;
@ -720,6 +721,13 @@ public final class AWTAccessor {
void setPlatformResources(ResourceBundle bundle);
}
/*
* An accessor object for the InvocationEvent class
*/
public interface InvocationEventAccessor {
void dispose(InvocationEvent event);
}
/*
* Accessor instances are initialized in the static initializers of
* corresponding AWT classes by using setters defined below.
@ -748,6 +756,7 @@ public final class AWTAccessor {
private static DefaultKeyboardFocusManagerAccessor defaultKeyboardFocusManagerAccessor;
private static SequencedEventAccessor sequencedEventAccessor;
private static ToolkitAccessor toolkitAccessor;
private static InvocationEventAccessor invocationEventAccessor;
/*
* Set an accessor object for the java.awt.Component class.
@ -1159,4 +1168,18 @@ public final class AWTAccessor {
return toolkitAccessor;
}
/*
* 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;
}
}