Bug 1478 - macOS 14.0 JOGL freezes when opening other JFrame before JOGL frame
Summary: macOS 14.0 JOGL freezes when opening other JFrame before JOGL frame
Status: UNCONFIRMED
Alias: None
Product: Jogl
Classification: JogAmp
Component: awt (show other bugs)
Version: 2.6.0
Hardware: All macosx
: P4 major
Assignee: Sven Gothel
URL: https://forum.jogamp.org/freeze-on-ma...
Depends on:
Blocks:
 
Reported: 2023-11-22 21:45 CET by Sibo Van Gool
Modified: 2024-04-24 13:00 CEST (History)
1 user (show)

See Also:
Type: DEFECT
SCM Refs:
Workaround: ---


Attachments
Test logs (248.35 KB, application/zip)
2023-11-22 21:45 CET, Sibo Van Gool
Details
threaddump-deadlock-awt-edt-setvisible01 (16.91 KB, text/plain)
2024-03-12 09:40 CET, Sven Gothel
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Sibo Van Gool 2023-11-22 21:45:05 CET
Created attachment 864 [details]
Test logs

Ever since I updated to macOS 13 (and a month ago to macOS 14), my Java Swing application freezes when launching a JOGL window. This issue does not occur on Windows or Linux, nor did it exist in macOS 12 or older. Also very strangely, when I first upgraded macOS to version 13, this bug occurred, but then, after some days the issue magically disappeared. Now that I upgraded to macOS 14, the issue returned and is permanent. No code changes were performed; the program stayed exactly the same.

This is the stack when the program freezes:
```
wait:-1, Object (java.lang)
wait:338, Object (java.lang)
RunOnMainThread:318, OSXUtil (jogamp.nativewindow.macosx)
CreateNSWindow:161, OSXUtil (jogamp.nativewindow.macosx)
lockSurfaceImpl:311, MacOSXJAWTWindow (jogamp.nativewindow.jawt.macosx)
lockSurface:708, JAWTWindow (com.jogamp.nativewindow.awt)
createJAWTDrawableAndContext:724, GLCanvas (com.jogamp.opengl.awt)
addNotify:619, GLCanvas (com.jogamp.opengl.awt)
addNotify:2804, Container (java.awt)
addNotify:4839, JComponent (javax.swing)
addNotify:2804, Container (java.awt)
addNotify:4839, JComponent (javax.swing)
addNotify:2804, Container (java.awt)
addNotify:4839, JComponent (javax.swing)
addNotify:729, JRootPane (javax.swing)
addNotify:2804, Container (java.awt)
addNotify:791, Window (java.awt)
addNotify:495, Frame (java.awt)
show:1053, Window (java.awt)
show:1728, Component (java.awt)
setVisible:1675, Component (java.awt)
setVisible:1036, Window (java.awt)
```

I was able to create an SSCCE of the problem. When I run this Java Swing code, my program freezes:

```Java
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Rectangle;

public class Test3D {
        public static void main(String[] args) {
                JFrame frame = new JFrame();
                SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                                frame.setVisible(true);
                        }
                });

                PhotoFrame pa = new PhotoFrame();
                SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                                pa.setVisible(true);
                        }
                });
        }

        private static class PhotoFrame extends JFrame {
                public PhotoFrame() {
                        PhotoPanel photoPanel = new PhotoPanel();
                        setContentPane(photoPanel);
                }

        }

        private static class PhotoPanel extends JPanel implements GLEventListener {
                PhotoPanel() {
                        this.setLayout(new BorderLayout());
                        initGLCanvas();
                }

                private void initGLCanvas() {
                        Component canvas;
                        try {
                                final GLProfile glp = GLProfile.get(GLProfile.GL2);
                                final GLCapabilities caps = new GLCapabilities(glp);
                                canvas = new GLCanvas(caps); // NOTE: using GLJPanel did not work either
                                this.add(canvas, BorderLayout.CENTER);
                        } catch (Throwable t) {
                                this.add(new JLabel("Unable to load 3d Libraries: " + t.getMessage()));
                        }
                }

                @Override
                public void paintImmediately(Rectangle r) { }

                @Override
                public void paintImmediately(int x, int y, int w, int h) { }

                @Override
                public void display(final GLAutoDrawable drawable) { }

                @Override
                public void init(final GLAutoDrawable drawable) { }

                @Override
                public void dispose(GLAutoDrawable glAutoDrawable) { }

                @Override
                public void reshape(GLAutoDrawable glAutoDrawable, int i, int i1, int i2, int i3) { }
        }
}
```

**However**, when I **change the order** of execution in the main method by first setting PhotoFrame visible and then the normal frame (instead of vice versa), the application does **not freeze**:
```Java
public static void main(String[] args) {
                PhotoFrame pa = new PhotoFrame();
                SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                                pa.setVisible(true);
                        }
                });

                JFrame frame = new JFrame();
                SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                                frame.setVisible(true);
                        }
                });
        }

```

Another example of a freeze scenario (same code, just different order):
```Java
public static void main(String[] args) {
                JFrame frame = new JFrame();
                PhotoFrame pa = new PhotoFrame();

                SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                                frame.setVisible(true);
                        }
                });
                SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                                pa.setVisible(true);
                        }
                });
        }
```

In the above code, when switching the order of the two runnables, the application does not freezes. Also when I comment out either one of the runnables, the application does not freezes. Placing the two `setVisible` calls in the same invokeLater call has the same effect: **the application only freezes when `frame.setVisible(true);` is called before `pa.setVisible(true);`**.


I was able to solve the above freezing by starting `initGLCanvas()` in a new thread:
```Java
new Thread(() -> {
        initGLCanvas();
}).start();
```

----

Content after running `sh etc/test.sh` in jogamp-all-platforms:
```
/Users/SiboVanGool/.jenv/shims/java
java version "17.0.1" 2021-10-19 LTS
Java(TM) SE Runtime Environment (build 17.0.1+12-LTS-39)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.1+12-LTS-39, mixed mode, sharing)
LIBXCB_ALLOW_SLOPPY_LOCK:
LIBGL_DRIVERS_PATH:
LIBGL_DEBUG:
java
CLASSPATH: jar/gluegen-rt.jar:jar/jogl-all.jar

forceES2    false
forceES3    false
forceGL3    false
forceGL4ES3 false
-----------------------------------------------------------------------------------------------------
Platform: MACOS / Mac OS X 14.0 (14.0.0), aarch64 (ARM64, EABI_AARCH64), 10 cores, littleEndian true
MachineDataInfo: runtimeValidated true, 32Bit false, primitive size / alignment:
  int8    1 / 1, int16   2 / 2
  int     4 / 4, long    8 / 8
  int32   4 / 4, int64   8 / 8
  float   4 / 4, double  8 / 8, ldouble 8 / 8
  pointer 8 / 8, page    16384
Platform: Java Version: 17.0.1 (17.0.1u0), VM: Java HotSpot(TM) 64-Bit Server VM, Runtime: Java(TM) SE Runtime Environment
Platform: Java Vendor: Oracle Corporation, https://java.oracle.com/, Java17, dynamicLib: true, AWT enabled: true
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
Package: com.jogamp.common
Extension Name: com.jogamp.common
Specification Title: GlueGen Java Bindings Generator
Specification Vendor: JogAmp Community
Specification Version: 2.5
Implementation Title: GlueGen Run-Time
Implementation Vendor: JogAmp Community
Implementation Vendor ID: com.jogamp
Implementation URL: http://jogamp.org/
Implementation Version: 2.5.0
Implementation Build: 2.5-b967-20230818
Implementation Branch: origin/master
Implementation Commit: a235ae5dae463afa16f62f48bf62f896efa80b68
Implementation SHA Sources: 784913ee2d456eede9cfaf94e1182ff484f24107548dee8655d7207b858936ea
Implementation SHA Classes: 2ccd03d934cccce4f0bcc44aa3dc5c1999382abe812245c6bfbc5c1f8467d56f
Implementation SHA Classes-this: eceeebdce7de6d72726a1dd2b74d9716c6048db47a3ac197bf9ab88f09e9186c
Implementation SHA Natives: eb1fad0f383f4b918219d2c856f5ca10474433692e7d6f79920989a74d3cc64b
Implementation SHA Natives-this: 0
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
Package: com.jogamp.opengl
Extension Name: com.jogamp.opengl
Specification Title: Java Bindings for OpenGL API Specification
Specification Vendor: JogAmp Community
Specification Version: 2.5
Implementation Title: Java Bindings for OpenGL Runtime Environment
Implementation Vendor: JogAmp Community
Implementation Vendor ID: com.jogamp
Implementation URL: http://jogamp.org/
Implementation Version: 2.5.0
Implementation Build: 2.5-b1533-20230818
Implementation Branch: origin/master
Implementation Commit: 70f62ca5d121e5e71548246d468b5e7baa5faf25
Implementation SHA Sources: null
Implementation SHA Classes: null
Implementation SHA Classes-this: null
Implementation SHA Natives: null
Implementation SHA Natives-this: null
-----------------------------------------------------------------------------------------------------
GLProfiles on device MacOSXGraphicsDevice[type .macosx, connection decon, unitID 0, handle 0x0, owner false, NullToolkitLock[obj 0x2d8f65a4]]
	Natives
		GL4bc 	false
		GL4 	true [4.1 (Core profile, arb, compat[ES2, ES3], FBO, hardware)]
		GLES3 	false
		GL3bc 	false
		GL3 	true [4.1 (Core profile, arb, compat[ES2, ES3], FBO, hardware)]
		GL2 	true [2.1 (Compat profile, arb, compat[], FBO, hardware)]
		GLES2 	false
		GLES1 	false
		Count	3 / 8
	Common
		GL4ES3 	true
		GL2GL3 	true
		GL2ES2 	true
		GL2ES1 	true
	Mappings
		GL2ES1 	GLProfile[GL2ES1/GL2.hw]
		GL4ES3 	GLProfile[GL4ES3/GL4.hw]
		GL2ES2 	GLProfile[GL2ES2/GL4.hw]
		GL2 	GLProfile[GL2/GL2.hw]
		GL4 	GLProfile[GL4/GL4.hw]
		GL3 	GLProfile[GL3/GL4.hw]
		GL2GL3 	GLProfile[GL2GL3/GL4.hw]
		default GLProfile[GL2/GL2.hw]
		Count	7 / 12


Capabilities for MacOSXGraphicsDevice[type .macosx, connection decon, unitID 0, handle 0x0, owner false, NullToolkitLock[obj 0x2d8f65a4]]
	none


Requesting: GLCaps[rgba 8/8/8/0, opaque, accum-rgba 0/0/0/0, dp/st/ms 16/0/0, dbl, mono  , hw, GLProfile[GL2/GL2.hw], on-scr[.]]
Main Monitor: Monitor[Id 0x1 [primary], 344 x 222 mm, pixelScale [2.0, 2.0], viewport[pixel [ 0 / 0  3456 x 2234 ], window [ 0 / 0  1728 x 1117 ]], orig [Id 0x36, [ 3456 x 2234 pixels x 32 bpp ] @ 120.0 Hz, flags [], 0 degr], curr [Id 0x36, [ 3456 x 2234 pixels x 32 bpp ] @ 120.0 Hz, flags [], 0 degr], modeChanged false, modeCount 528]
    pixel/mm [10.046512, 10.063063]
    pixel/in [255.1814, 255.60179]
-----------------------------------------------------------------------------------------------------
MacOSXGraphicsDevice[type .macosx, connection decon, unitID 0, handle 0x0, owner false, NullToolkitLock[obj 0x2d8f65a4]]:
	Natives
		GL4bc 	false
		GL4 	true [4.1 (Core profile, arb, compat[ES2, ES3], FBO, hardware)]
		GLES3 	false
		GL3bc 	false
		GL3 	true [4.1 (Core profile, arb, compat[ES2, ES3], FBO, hardware)]
		GL2 	true [2.1 (Compat profile, arb, compat[], FBO, hardware)]
		GLES2 	false
		GLES1 	false
		Count	3 / 8
	Common
		GL4ES3 	true
		GL2GL3 	true
		GL2ES2 	true
		GL2ES1 	true
	Mappings
		GL2ES1 	GLProfile[GL2ES1/GL2.hw]
		GL4ES3 	GLProfile[GL4ES3/GL4.hw]
		GL2ES2 	GLProfile[GL2ES2/GL4.hw]
		GL2 	GLProfile[GL2/GL2.hw]
		GL4 	GLProfile[GL4/GL4.hw]
		GL3 	GLProfile[GL3/GL4.hw]
		GL2GL3 	GLProfile[GL2GL3/GL4.hw]
		default GLProfile[GL2/GL2.hw]
		Count	7 / 12

Swap Interval  1
GL Profile     GLProfile[GL2/GL2.hw]
GL Version     2.1 (Compat profile, arb, compat[], FBO, hardware) - 2.1 Metal - 86 [GL 2.1.0, vendor 0.0.0 (n/a)]
Quirks         [NoOffscreenBitmap, GL4NeedsGL3Request, NeedSharedObjectSync]
Impl. class    jogamp.opengl.gl4.GL4bcImpl
GL_VENDOR      Apple
GL_RENDERER    Apple M1 Pro
GL_VERSION     2.1 Metal - 86
GLSL           true, has-compiler-func: true, version: 1.20 / 1.20.0
GL FBO: basic true, full true
GL_EXTENSIONS  133
GLX_EXTENSIONS 0
-----------------------------------------------------------------------------------------------------
Requested: GLCaps[rgba 8/8/8/0, opaque, accum-rgba 0/0/0/0, dp/st/ms 16/0/0, dbl, mono  , hw, GLProfile[GL2/GL2.hw], on-scr[.]]
Chosen   : GLCaps[rgba 8/8/8/8, opaque, accum-rgba 0/0/0/0, dp/st/ms 32/0/0, dbl, mono  , hw, GLProfile[GL2/GL2.hw], on-scr[.]]
GL impl. class jogamp.opengl.gl4.GL4bcImpl
```

I used the JOGL JAR files from `gluegen_967-joal_684-jogl_1533-jocl_1171`
Comment 1 Sibo Van Gool 2023-11-22 21:45:29 CET
Taken from this discussion: https://forum.jogamp.org/freeze-on-macos-Sonoma-td4043021.html.
Comment 2 Julien Gouesse 2023-11-23 10:07:26 CET
The gilt on the gingerbread would consist in running the existing unit tests under Mac OS Sonoma, maybe some of them break.
Comment 3 Sven Gothel 2023-11-26 09:36:17 CET
Thank you Sibo and Julien for handling.
Earmarked for next version 2.6.0
Comment 4 Sibo Van Gool 2023-11-26 21:53:54 CET
(In reply to Julien Gouesse from comment #2)
I'd be happy to help with that if you can guide me through the process. I was able to compile JOGL and Gluegen a while ago, so I think/hope I already have a bunch of the required tools set up to run the unit tests.
Comment 5 Sven Gothel 2024-03-12 09:40:44 CET
Created attachment 890 [details]
threaddump-deadlock-awt-edt-setvisible01
Comment 6 Sven Gothel 2024-03-12 09:43:02 CET
On 2024-02-23 Harvey sent me the following information,
slightly edited here:
+++
Got a deadlock report from a JaamSim user on MacOS Sonoma 
and managed to get a thread dump from them.

It looks like a deadlock in the AWT event thread related 
to setVisible around line 129, see attachment 890 [details].

You can see it running into the JOGL code to
run things on the main thread and then waiting, but it's being run on
the AWT Event thread which generally brings things a a screaming halt
after that.

I'm not able to reproduce on my Mac (of course!) so this is all I have
to go on for now, not sure if you've been considering if this is a bug
in JOGL, or in the way it's being called...advice welcome if you have
any, otherwise hopefully this provides some insight if/when you get
around to bug 1478.
+++
Comment 7 Sibo Van Gool 2024-03-17 15:47:17 CET
(In reply to Sven Gothel from comment #6)
If you need me to test something, I'd be happy to help!

If it's not a bug, but a bad JOGL init, then what would the correct init be in the SSCCE?
Comment 8 Julien Gouesse 2024-04-24 13:00:53 CEST
Pierre Nugues asked me to post this here:

I would like to confirm this bug on macOS that showed when I upgraded my system with Sonoma. I am using Corretto, but I could reproduce it with other versions of Oracle’s Java.

I found a workaround that maybe could help understand it :
Java freezes in the function getBestConfiguration() of:
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getBestConfiguration(template)

Setting a breakpoint at getBestConfiguration() enables Java to stop freezing. I am using IntelliJ with their standard debugger.

I have no explanation for this just that it works.