Bug 1393

Summary: MacOS 10.14.6 + OpenJDK11U produces occasional freezes on AppKit Main Thread
Product: [JogAmp] Newt Reporter: Sven Gothel <sgothel>
Component: macosxAssignee: Sven Gothel <sgothel>
Status: RESOLVED FIXED    
Severity: major CC: askinner, jani
Priority: P4    
Version: 2.4.0   
Hardware: All   
OS: macosx   
Type: DEFECT SCM Refs:
b12a80e386b12d9d8fa63cf07124f8da989dcd04 e33aa16904d8abddaeceb1374ffa45bd45a96210 7e76df3a05b7eb2404cb4584ee0b34ea287eb9bf b8db98376069a72ad40b7ef2fe2d9003aea2b091 ecc6794670b31d859763eb363ed3ead15d757977 b0a222100ce8425485bea201adf28dc6509333ad 4a072cd1c09d3f2ba5fd04033091836d195c9409 2e59792eba285d7cd3c2f4f4c78838b8cc8918f7 12eed5d38616d23b6e8e2e5b497dfc2f54d90c90 999e1ca3ec1a406d3dba65f0bae79054580fb287
Workaround: ---
Bug Depends on: 1370    
Bug Blocks:    

Description Sven Gothel 2019-09-09 08:54:44 CEST
Latest manual tests after resolving Bug 1389
disclosed a few occasional freezes using NEWT + Java11.

These are related to probable AWT changes since Java8.

MacOS 10.14.6 freezes 4 / 273
====================================
com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext01VSyncAnimNEWT test07ExclPre_4Win
com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext11VSyncAnimNEWT
com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext02FPSAnimNEWT
com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext12FPSAnimNEWT

Inspection of proper utilization of NSWindow/NSView etc 
on AppKit Main-Thread is required. 

May utilize 'Main Thread Checker', see
<https://developer.apple.com/documentation/code_diagnostics/main_thread_checker?language=objc>

Further we should align the Main-Thread usage in the macosx implementation
with our new ios implementation.
See commit 004c67c73a0309158c30929cd0d6513e23f34803 
which already simplifies the createWindow code.
Comment 1 Sven Gothel 2019-09-09 09:11:12 CEST
Just for the sake of a little documentation:

We have to ensure avoiding deadlocks the likes of:

Threads: USR, EDT, AppKit
(USR the user thread, any ..)
(EDT the NEWT EDT thread for lifecycle and events/tasks)
(AppKit MacOS APPKit Main-Thread)

USR -- cmd --> EDT (blocking pending action)

from here on:

EDT -- osx --> APK (one of those cocoa/NS actions)

EDT <-- blocking -- APK (we issue a deferred-and-wait NEWT command on EDT)

Result ** DEADLOCK **

The only critical synchronous action w/ NEWT are
lifecycle operations, where we demand handles to be realized.
E.g. createWindow(..) up until the native handles exist,
however, the actual 'setVisible' can be spun off-thread on the APK.
Comment 2 Sven Gothel 2019-09-09 09:39:49 CEST
resolved as described:

commit b12a80e386b12d9d8fa63cf07124f8da989dcd04
Author: Sven Gothel <sgothel@jausoft.com>
Date:   Mon Sep 9 09:29:43 2019 +0200

    Bug 1393: Run orderFront0(=setVisible) async off-thread on AppKit after sync AppKit NSWindow creation
    
    MacOS 10.14.6 + OpenJDK11U produces occasional freezes on AppKit Main Thread
    
    Latest manual tests after resolving Bug 1389
    disclosed a few occasional freezes using NEWT + Java11.
    
    These are related to probable AWT changes since Java8,
    as these do not occur with Java8.
    
    Fix: Spun off orderFront0(=setVisible) async off-thread on AppKit after sync AppKit NSWindow creation.
    
    This fix also aligns the macos createWindow code with the new simplified ios implementation,
    see commit 004c67c73a0309158c30929cd0d6513e23f34803


commit e33aa16904d8abddaeceb1374ffa45bd45a96210
Author: Sven Gothel <sgothel@jausoft.com>
Date:   Mon Sep 9 09:33:23 2019 +0200

    Bug 1393: MacOS/iOS: Issue updateSizePosInsets0 async to AppKit Main-Thread
    
    Additionally, setPointerIcon0 must also be made async on AppKit (instead of wait),
    we have to assume/hope the user won't pull the PointerIconImpl instance in-between ;-)
    Hence removing the comment regarding the lifecycle.


commit 7e76df3a05b7eb2404cb4584ee0b34ea287eb9bf (HEAD -> master)
Author: Sven Gothel <sgothel@jausoft.com>
Date:   Mon Sep 9 09:36:50 2019 +0200

    Bug 1393: OSXUtil: Optionally inject Apple's 'Main Thread Checker'
    
    To allow proper testing of whether all AppKit calls are performed on its Main-Thread where required,
    we inject the libMainThreadChecker.dylib when property 'nativewindow.debug.OSXUtil.MainThreadChecker' is set.
    
    See <https://developer.apple.com/documentation/code_diagnostics/main_thread_checker?language=objc>
    Lib-Name: /Applications/Xcode.app/Contents/Developer/usr/lib/libMainThreadChecker.dylib
Comment 3 Sven Gothel 2019-09-11 04:18:16 CEST
commit b8db98376069a72ad40b7ef2fe2d9003aea2b091

    Bug 1393: Add window position validation in TestDisplayLifecycle*NEWT
    
    The OSX fixes for bug 1393 spun off certain tasks like position/size gathering async to AppKit,
    hence we should validate whether both are valid.
    
    Further the TestDisplayLifecycle02NEWT had one bug,
    it retrieved 'screen.getViewportInWindowUnits()' while it was not yet initialized.
Comment 4 Sven Gothel 2019-09-11 07:41:51 CEST
reopening: further investigation shows that subsequent 'run on main-thread' task has been spun off to the app-kit thread, but not processed.

however, the app-kit thread has not being locked within our EDT
as shown in comment 1.
Comment 5 Sven Gothel 2019-11-28 02:23:55 CET
ecc6794670b31d859763eb363ed3ead15d757977

    Bug 1393: Adding test cases setting visibility before enabling exclusive context thread animator
    
    MacOS Java11 freezes occur on 3rd NEWT window creation (orderFront) after enabling exclusive context thread animator.
    Here we add set visibility upfront which does not trigger the freeze on the AppKit main thread.
    Note: OpenJDK8 works flawlessly.
    For some reason, the exclusive context thread enabled animator interferes when 'orderFront' is issued.

+++

b0a222100ce8425485bea201adf28dc6509333ad

    Bug 1393: MacOS: Implement AppKit EDTUtil operating solely on main-thread
    
    Introducing boolean property 'newt.macos.useAppKitEDTUtil', which defaults to 'false'.
    If enabled, the new AppKitEDTUtil is being used, operating on the AppKit main thread.
    This is used to ease debugging Bug 1393, minimizing thread context switches.

+++

4a072cd1c09d3f2ba5fd04033091836d195c9409

    Bug 1393: MacOS: Wait for window position setting on main-thread (blocking)
    
    Also issue the orderFront0 call within createWindow1 (aligned with IOS code)
Comment 6 Sven Gothel 2019-12-08 04:56:37 CET
2e59792eba285d7cd3c2f4f4c78838b8cc8918f7
Make window position check more tolerant (2x insets or 64 pixels, whichever is greater)
    
    Certain WM's may modify the windowing position 'a little', which has been experienced on one X11 server
    during invisible setting. The insets were removed and its value added to the position!
    
    We could argue that this is an issue in our windowing code, however, the WM is free to reposition a window.
    
    Refines commit b8db98376069a72ad40b7ef2fe2d9003aea2b091
Comment 7 Sven Gothel 2019-12-08 08:37:17 CET
*** Bug 1398 has been marked as a duplicate of this bug. ***
Comment 8 Sven Gothel 2019-12-08 09:46:19 CET
12eed5d38616d23b6e8e2e5b497dfc2f54d90c90
Resolve EDT + AppKit Deadlock with native parenting: Fetch parent screen position directly w/o locking.
Comment 9 Sven Gothel 2020-01-01 00:00:24 CET
passed unit tests ..
Comment 10 Sven Gothel 2020-01-02 04:45:35 CET
(In reply to Sven Gothel from comment #8)

jogl commit 999e1ca3ec1a406d3dba65f0bae79054580fb287

    Bug 1393: MacOS: getLocationOnScreen w/ JAWT Parent: Use parent's unblocking specialization
    
    On MacOS, commit 12eed5d38616d23b6e8e2e5b497dfc2f54d90c90 replaced all
    parent.getLocationOnScreen(..) calls with OSXUtil.GetLocationOnScreen(parentHandle, ..)
    avoiding the EDT + Appkit Deadlock with native parenting.
    
    On MacOS AWT and JAWT are using offscreen CALayer since Java >= 1.7.0,
    therefor the MacOSXJAWTWindow's native window handle can't be used to gather
    the screen position via OSXUtil.
    
    However, the JAWT Window specialization MacOSXJAWTWindow implements a non-locking code-path
    and we can decide to use it by querying the general interface OffscreenLayerOption.