On Mon, 15 Jul 2024 22:08:12 GMT, Andy Goryachev <ango...@openjdk.org> wrote:

>> This PR solves two related bugs that are caused by events being delivered 
>> while the FX runtime is in the process of shutting down. These bugs are 
>> related enough that I think they need to be addressed at the same time. 
>> While debugging and developing the test, I saw one or the other or both in 
>> various test runs. The system test included with this program verifies that 
>> there is no crash and no exception, so will catch either failure mode.
>> 
>> This can happen when there is a full-screen window showing during shutdown 
>> on macOS, since full screen enter / exit uses a nested event loop that 
>> affects the order of operation. This could theoretically happen in other 
>> cases, thus the fix does not involve checking whether we are in full-screen 
>> or whether there is a nested event loop.
>> 
>> The fix does the following:
>> 
>> 1. `GlassWindow+Overrides.m`: Check that the JVM is still running before 
>> calling the Java notification method in `windowDidResignKey` and 
>> `windowShouldClose`. This matches what is already done for other similar 
>> methods in this class. This is the fix for JDK-8335630.
>> 2. `Window.java` and `View.java`: Check whether the Application instance is 
>> null in the event notification callbacks, and skip handling the event if it 
>> is. This is the fix for JDK-8299738.
>> 
>> Note that the fix for 2 is in platform-independent code. This should be 
>> fine, since we would want to skip the event handling callback on any other 
>> platform if it were done during shutdown, in order to avoid the ISE.
>> 
>> I have included a system test that passes on all platforms. On macOS, the 
>> test will fail without the fix and pass with the fix.
>> 
>> Details of the fix are below:
>> 
>> `Platform::exit` is called by the application to shutdown the JavaFX 
>> toolkit. The implementation of `Platform::exit` calls `Toolkit::exit` on the 
>> JavaFX Application thread, which in turn calls glass 
>> `Application::terminate` to shut it down. `Application::terminate` will 
>> close all the native windows, and call `finishTerminating` to terminate the 
>> native event loop and detach the thread from the JVM. This is asynchronous, 
>> at least on macOS, and will schedule the termination by posting a native 
>> event to the event loop.
>> 
>> on macOS 13, and sometimes on macOS 14, a Window or View event handler can 
>> be called between `Toolkit::exit`/`Application::terminate` (which sets the 
>> Toolkit's cached thread to null and the glass Application instance to null) 
>> and the JVM shutdown. This will make a JNI upcall to the appropriate 
>> Window...
>
> modules/javafx.graphics/src/main/java/com/sun/glass/ui/View.java line 533:
> 
>> 531:     private boolean shouldHandleEvent() {
>> 532:         // Don't send any more events if the application has shutdown
>> 533:         if (Application.GetApplication() == null) {
> 
> Should we declare `Application.application` field as volatile?
> 
> I see interleaved multi-threaded access pattern:
> 
> 
> thread=JavaFX-Launcher
> CREATE thread=JavaFX-Launcher
> thread=JavaFX-Launcher
> thread=Thread-2
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX-Launcher
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX-Launcher
> thread=JavaFX Application Thread
> thread=PulseTimer-CVDisplayLink thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=QuantumRenderer-0
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=PulseTimer-CVDisplayLink thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX-Launcher
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=JavaFX Application Thread
> thread=Java...

Other threads may still not see the current value of the 
`Application.application` field. Is it safe for other threads to use the 
`Application` instance after the field has been set to `null`?

-------------

PR Review Comment: https://git.openjdk.org/jfx/pull/1506#discussion_r1678465264

Reply via email to