Commit 52f2057
committed
Fix JavaFX + AWT EDT macOS deadlocks
This commit "fixes" deadlocks on macOS where the AWT
EDT and JavaFX threading models clash. On macOS, but
not Windows or Linux, all GUI things happen with AppKit
and the Cocoa event loop. Additionally on macOS only
**one** event dispatch thread (EDT) is allowed per
event loop which means that JavaFX and AWT effectively
share the same thread resources. The specific case
that this addresses is flimlib/flimj-ui#35. FLIMJ (i.e.
flimj-ui) is a JavaFX application that needs to interact
with AWT UI elements. Briefly when a user attempts to
export images back to Fiji by clicking "Export", the
application hangs both the plugin and Fiji in general.
From *my* understanding this is what is happening:
1. The user clicks "Export" which triggers a GUI event
which ultimately gets run with `invokeAndWait()` which
is a blocking call until the export function returns.
Because the event is tied to the GUI, the JavaFX now
has a lock on the Cocoa event loop until export is complete.
2. What the "Export" button does is show the selected images
in Fiji, which means we need to use AWT now. The `show()` call
is made and tiggers its necessary AWT code which ultimately
asks for a lock on the Cocoa event loop to acess the GUI screen.
3. The AWT thread never gets the Cocoa event loop because JavaFX has
it and wont give it up until AWT shows the images and returns. But
AWT **cant** becaues JavaFX has the lock. This is our threading
dead lock and also why we see hangs here in the thread dumps:
at sun.awt.CGraphicsDevice.nativeGetScreenInsets (Native Method)
at org.scijava.thread.DefaultThreadService.invoke (line 114)
This doesn't happen on Windows or Linux becauase, according
to the bug discussion linked below, its possible to have
more than one EDT on those systems. Just not macOS. What this commit
does is instead of using the blocking `invoke()` call via the ThreadService
which gets us in this trouble, we instead detect a JavaFX thread and
do an async queue instead. This means that JavaFX doesn't lock the
Cocoa event loop, apperently, and AWT is safe to do its thing and return.
See https://bugs.openjdk.org/browse/JDK-8087465 for
more details on this JavaFX + AWT bug.1 parent d14ad9b commit 52f2057
1 file changed
+16
-0
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
150 | 150 | | |
151 | 151 | | |
152 | 152 | | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
153 | 169 | | |
154 | 170 | | |
155 | 171 | | |
| |||
0 commit comments