8088132: [Swing, singleThread] ClassCastException in nested event loop when showing multiple message dialogs in SwingNode

Reviewed-by: serb
This commit is contained in:
Prasanta Sadhukhan 2017-09-26 10:46:23 +05:30
parent b8ca97f45c
commit ebf03d174d
2 changed files with 90 additions and 9 deletions

View file

@ -30,6 +30,8 @@ import java.awt.event.WindowEvent;
import java.awt.peer.ComponentPeer;
import java.awt.peer.LightweightPeer;
import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.LinkedList;
import java.util.Iterator;
import java.util.ListIterator;
@ -77,6 +79,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
private boolean consumeNextKeyTyped;
private Component restoreFocusTo;
private static boolean fxAppThreadIsDispatchThread;
static {
AWTAccessor.setDefaultKeyboardFocusManagerAccessor(
new AWTAccessor.DefaultKeyboardFocusManagerAccessor() {
@ -84,6 +88,13 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
dkfm.consumeNextKeyTyped(e);
}
});
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
fxAppThreadIsDispatchThread =
"true".equals(System.getProperty("javafx.embed.singleThread"));
return null;
}
});
}
private static class TypeAheadMarker {
@ -264,13 +275,41 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
}
SunToolkit.postEvent(targetAppContext, se);
if (EventQueue.isDispatchThread()) {
EventDispatchThread edt = (EventDispatchThread)
Thread.currentThread();
edt.pumpEvents(SentEvent.ID, new Conditional() {
if (Thread.currentThread() instanceof EventDispatchThread) {
EventDispatchThread edt = (EventDispatchThread)
Thread.currentThread();
edt.pumpEvents(SentEvent.ID, new Conditional() {
public boolean evaluate() {
return !se.dispatched && !targetAppContext.isDisposed();
}
});
} else {
if (fxAppThreadIsDispatchThread) {
Thread fxCheckDispatchThread = new Thread() {
@Override
public void run() {
while (!se.dispatched && !targetAppContext.isDisposed()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
break;
}
}
}
};
fxCheckDispatchThread.start();
try {
// check if event is dispatched or disposed
// but since this user app thread is same as
// dispatch thread in fx when run with
// javafx.embed.singleThread=true
// we do not wait infinitely to avoid deadlock
// as dispatch will ultimately be done by this thread
fxCheckDispatchThread.join(500);
} catch (InterruptedException ex) {
}
}
}
} else {
synchronized (se) {
while (!se.dispatched && !targetAppContext.isDisposed()) {

View file

@ -25,6 +25,8 @@
package java.awt;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.LinkedList;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
@ -55,6 +57,8 @@ class SequencedEvent extends AWTEvent implements ActiveEvent {
private AppContext appContext;
private boolean disposed;
private static boolean fxAppThreadIsDispatchThread;
private Thread fxCheckSequenceThread;
static {
AWTAccessor.setSequencedEventAccessor(new AWTAccessor.SequencedEventAccessor() {
public AWTEvent getNested(AWTEvent sequencedEvent) {
@ -68,6 +72,13 @@ class SequencedEvent extends AWTEvent implements ActiveEvent {
return new SequencedEvent(event);
}
});
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
fxAppThreadIsDispatchThread =
"true".equals(System.getProperty("javafx.embed.singleThread"));
return null;
}
});
}
/**
@ -83,6 +94,21 @@ class SequencedEvent extends AWTEvent implements ActiveEvent {
// All AWTEvents that are wrapped in SequencedEvents are (at
// least currently) implicitly generated by the system
SunToolkit.setSystemGenerated(nested);
if (fxAppThreadIsDispatchThread) {
fxCheckSequenceThread = new Thread() {
@Override
public void run() {
while(!isFirstOrDisposed()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
break;
}
}
}
};
}
synchronized (SequencedEvent.class) {
list.add(this);
}
@ -106,13 +132,29 @@ class SequencedEvent extends AWTEvent implements ActiveEvent {
if (getFirst() != this) {
if (EventQueue.isDispatchThread()) {
EventDispatchThread edt = (EventDispatchThread)
Thread.currentThread();
edt.pumpEvents(SentEvent.ID, new Conditional() {
public boolean evaluate() {
return !SequencedEvent.this.isFirstOrDisposed();
if (Thread.currentThread() instanceof EventDispatchThread) {
EventDispatchThread edt = (EventDispatchThread)
Thread.currentThread();
edt.pumpEvents(SentEvent.ID, new Conditional() {
public boolean evaluate() {
return !SequencedEvent.this.isFirstOrDisposed();
}
});
} else {
if (fxAppThreadIsDispatchThread) {
fxCheckSequenceThread.start();
try {
// check if event is dispatched or disposed
// but since this user app thread is same as
// dispatch thread in fx when run with
// javafx.embed.singleThread=true
// we do not wait infinitely to avoid deadlock
// as dispatch will ultimately be done by this thread
fxCheckSequenceThread.join(500);
} catch (InterruptedException e) {
}
}
});
}
} else {
while(!isFirstOrDisposed()) {
synchronized (SequencedEvent.class) {