Summary: | Calling invoke(true,GLRunnable) on several GLCanvases in the same container causes a deadlock | ||
---|---|---|---|
Product: | [JogAmp] Jogl | Reporter: | Julien Gouesse <gouessej> |
Component: | core | Assignee: | Sven Gothel <sgothel> |
Status: | RESOLVED FIXED | ||
Severity: | major | CC: | gouessej, sgothel |
Priority: | --- | ||
Version: | 2 | ||
Hardware: | pc_all | ||
OS: | linux | ||
Type: | --- | SCM Refs: |
jogl c066dc997646643a98c35b7c70183930284544d1
jogl a3cb6bb14f410f67fccf5ccd4cd7ecc66f448389
|
Workaround: | --- | ||
Attachments: |
Ardor3D JOGL2 Patch Fix GLContext makeCurrent/release imbalance / commented-out workaround for old JOGL bug
partial revert of commit 4b5a0f6557d7152ec770bc13ad3c494449de0529 |
Description
Julien Gouesse
2012-04-02 17:15:45 CEST
It is reproducible on this machine: MS Win XP Pro x64 Ed Vr 2003 SP 2 Intel Core i3-2100 cpu @3.10GHz NVIDIA Quadro FX 1400 Driver Version 6.14.12.7628 Hi Actually, the original bug was caused by two bugs, one in my source code in Ardor3D's renderer based on JOGL 2.0, one in JOGL 2.0 itself. When using GLCanvas, the creation of the context fails if it is not performed on the OpenGL thread (AWT EDT by default) and the further successive OpenGL calls do not work fine if they are not done on the same thread too under Windows with some Nvidia graphics cards. I fixed this bug in Ardor3D by using GLCanvas.invoke(true, GLRunnable) to create the context and to perform all OpenGL calls. It works fine when a single GLCanvas is in a container (java.awt.Frame). However, there is a deadlock as soon as several GLCanvases are in the same container and it occurs everywhere, not only under Windows. It stays blocked on a call of JAWTUtil.lockToolkit() when pushing the runnable that makes current the context of the second GLCanvas. (In reply to comment #2) > Hi > > Actually, the original bug was caused by two bugs, one in my source code in > Ardor3D's renderer based on JOGL 2.0, one in JOGL 2.0 itself. > > When using GLCanvas, the creation of the context fails if it is not performed > on the OpenGL thread (AWT EDT by default) and the further successive OpenGL > calls do not work fine if they are not done on the same thread too under > Windows with some Nvidia graphics cards. In the pastebin post I read that the initialization, adding the GLCanvas, setVisible(true), is not done on the AWT-EDT. Even thought this shall be tolerated .. it's not perfectly clean. > I fixed this bug in Ardor3D by using > GLCanvas.invoke(true, GLRunnable) to create the context and to perform all > OpenGL calls. It works fine when a single GLCanvas is in a container > (java.awt.Frame). Using invoke for every single frame (maybe even multiple times) IMHO is overkill, since it creates an object on the fly and risks fluent processing due to GC behavior etc. However, it should work .. > > However, there is a deadlock as soon as several GLCanvases are in the same > container and it occurs everywhere, not only under Windows. It stays blocked on > a call of JAWTUtil.lockToolkit() when pushing the runnable that makes current > the context of the second GLCanvas. Can you produce a small test case for this, since it is impossible to see where your GLRunnable is claiming the AWT lock etc .. Thank you. (In reply to comment #3) > (In reply to comment #2) > > Hi > > > > Actually, the original bug was caused by two bugs, one in my source code in > > Ardor3D's renderer based on JOGL 2.0, one in JOGL 2.0 itself. > > > > When using GLCanvas, the creation of the context fails if it is not performed > > on the OpenGL thread (AWT EDT by default) and the further successive OpenGL > > calls do not work fine if they are not done on the same thread too under > > Windows with some Nvidia graphics cards. > > In the pastebin post I read that the initialization, adding the GLCanvas, > setVisible(true), > is not done on the AWT-EDT. Even thought this shall be tolerated .. it's not > perfectly clean. > Ok I'll use invokeAndWait to do it. > > I fixed this bug in Ardor3D by using > > GLCanvas.invoke(true, GLRunnable) to create the context and to perform all > > OpenGL calls. It works fine when a single GLCanvas is in a container > > (java.awt.Frame). > > Using invoke for every single frame (maybe even multiple times) IMHO is > overkill, > since it creates an object on the fly and risks fluent processing due to GC > behavior etc. > However, it should work .. > I create a GLRunnable for drawing once only. Can it still cause a problem due to GC behavior? Do you have another solution to suggest? > > > > However, there is a deadlock as soon as several GLCanvases are in the same > > container and it occurs everywhere, not only under Windows. It stays blocked on > > a call of JAWTUtil.lockToolkit() when pushing the runnable that makes current > > the context of the second GLCanvas. > > Can you produce a small test case for this, since it is impossible > to see where your GLRunnable is claiming the AWT lock etc .. > Thank you. Ok I'll do so as soon as possible. The GLRunnable seems to be stuck when creating a second context. Is there a similar example in NEWT in its JUnit tests? > > Using invoke for every single frame (maybe even multiple times) IMHO is > > overkill, > > since it creates an object on the fly and risks fluent processing due to GC > > behavior etc. > > However, it should work .. > > > I create a GLRunnable for drawing once only. Can it still cause a problem due > to GC behavior? Do you have another solution to suggest? You mean once per frame ? Even though the GC shall be capable of doing so on desktop, on mobile it's always a gamble .. but 10-60 temporary objects a second should be fine - maybe you even 'cache' those object in which case no GC trigger would exist at all. But if using this mechanism for frame rendering, why not using the listener model ? I introduced the GLRunnable to inject some event based GL commands usually not happening too frequently. However you like to do it (cached GLRunnable or listener or your own 'loop') it should work .. and is only a side discussion here, granted! > > > > > > > However, there is a deadlock as soon as several GLCanvases are in the same > > > container and it occurs everywhere, not only under Windows. It stays blocked on > > > a call of JAWTUtil.lockToolkit() when pushing the runnable that makes current > > > the context of the second GLCanvas. > > > > Can you produce a small test case for this, since it is impossible > > to see where your GLRunnable is claiming the AWT lock etc .. > > Thank you. > Ok I'll do so as soon as possible. The GLRunnable seems to be stuck when > creating a second context. Is there a similar example in NEWT in its JUnit > tests? I assume a shared GLContext from within a GLRunnable ? Here are some simple GLRunnable use cases .. src/test/com/jogamp/opengl/test/junit/graph/demos/ui/SceneUIController.java src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDebug01NEWT.java src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java src/test/com/jogamp/opengl/test/junit/newt/parenting/GLRunnableDummy.java src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01cSwingAWT.java Lately I ran into some 'chicken-egg' problem myself, i.e. creating a new shared context: src/test/com/jogamp/opengl/test/android/MovieSimpleActivity1.java It uses NEWT and runs on Android. GLRunnable solves the lifecycle issue of creating a 2nd GLMoviePlayer with information of the 1st one with information only available after the 1st player initialized itself. Since the latter is only possible w/ an initialized GLContext .. :) This API restriction in GLMediaPlayer I had to add due to some .. bugs with Tegra/Android .. yeah, sometime it's all a big compromise :) Would be great if your can provide a use case, so I can reproduce and hopefully fix it. Laters, .. Sven I get a hunch what could happen .. hmm. Even though it would be best to have a test case, can you provide a complete trace dump of the case when it deadlocks with the following flags: -Dnativewindow.debug.ToolkitLock.TraceLock -Djogamp.common.utils.locks.Lock.timeout=600000 -Djogamp.debug.Lock -Djogamp.debug.Lock.TraceLock 1) The increased timeout value (default 5s) to gain the lock would allow you to properly create a stack trace via jstack -l <pid> Please provide the log file and the stack trace. 2) Then pls provide a log file w/ the normal timeout of 5s but the other debug flags intact. This shall at least disclose the thread sitting on the lock. It might be the case where: T1: AWT-EDT: - execute GLRunnable - create resources while 'spawn off' to T2 T2: - attempt to create GLContext on T1 (AWT) *but it's locked already* and we came 'from their'. ? Thx .. cheers 2012-04-17 19:02:17 Full thread dump OpenJDK Client VM (20.0-b11 mixed mode): "Attach Listener" daemon prio=10 tid=0x8c9f4400 nid=0x300c runnable [0x00000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "com.google.common.base.internal.Finalizer" daemon prio=10 tid=0x8f3ea000 nid=0x2fd9 in Object.wait() [0x8d143000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x9b408290> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:133) - locked <0x9b408290> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:149) at com.google.common.base.internal.Finalizer.run(Finalizer.java:127) Locked ownable synchronizers: - None "AWT-EventQueue-0" prio=10 tid=0x8c9bc800 nid=0x2fd7 in Object.wait() [0x8f696000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x9b1bc9e0> (a java.awt.EventQueue) at java.lang.Object.wait(Object.java:502) at java.awt.EventQueue.getNextEvent(EventQueue.java:490) - locked <0x9b1bc9e0> (a java.awt.EventQueue) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:247) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177) at java.awt.EventDispatchThread.run(EventDispatchThread.java:138) Locked ownable synchronizers: - <0x9b1630c8> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) - <0x9b2ab790> (a jogamp.common.util.locks.RecursiveLockImpl01Unfairish$SingleThreadSync) - <0x9b2ac370> (a jogamp.common.util.locks.RecursiveLockImpl01Unfairish$SingleThreadSync) "AWT-Shutdown" prio=10 tid=0x8f33f000 nid=0x2fd5 in Object.wait() [0x8f77d000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x9b21ca98> (a java.lang.Object) at java.lang.Object.wait(Object.java:502) at sun.awt.AWTAutoShutdown.run(AWTAutoShutdown.java:281) - locked <0x9b21ca98> (a java.lang.Object) at java.lang.Thread.run(Thread.java:679) Locked ownable synchronizers: - None "main-SharedResourceRunner" daemon prio=10 tid=0x8fcb3400 nid=0x2fc5 in Object.wait() [0x8f53b000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x9b21ccf0> (a jogamp.opengl.SharedResourceRunner) at java.lang.Object.wait(Object.java:502) at jogamp.opengl.SharedResourceRunner.run(SharedResourceRunner.java:240) - locked <0x9b21ccf0> (a jogamp.opengl.SharedResourceRunner) at java.lang.Thread.run(Thread.java:679) Locked ownable synchronizers: - None "AWT-XAWT" daemon prio=10 tid=0xb6aa3400 nid=0x2fae waiting on condition [0x8f7ce000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x9b1630c8> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:838) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:871) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1201) at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:214) at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:290) at sun.awt.SunToolkit.awtLock(SunToolkit.java:264) at sun.awt.X11.XToolkit.waitForEvents(Native Method) at sun.awt.X11.XToolkit.run(XToolkit.java:568) at sun.awt.X11.XToolkit.run(XToolkit.java:543) at java.lang.Thread.run(Thread.java:679) Locked ownable synchronizers: - None "Java2D Disposer" daemon prio=10 tid=0x8fc46000 nid=0x2faa in Object.wait() [0x8f8d3000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x9b144890> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:133) - locked <0x9b144890> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:149) at sun.java2d.Disposer.run(Disposer.java:143) at java.lang.Thread.run(Thread.java:679) Locked ownable synchronizers: - None "Low Memory Detector" daemon prio=10 tid=0xb6a7c000 nid=0x2fa3 runnable [0x00000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "C1 CompilerThread0" daemon prio=10 tid=0xb6a7a000 nid=0x2fa2 waiting on condition [0x00000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "JDWP Command Reader" daemon prio=10 tid=0x089a8400 nid=0x2f9c runnable [0x00000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "JDWP Event Helper Thread" daemon prio=10 tid=0xb6a78400 nid=0x2f9b runnable [0x00000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "JDWP Transport Listener: dt_socket" daemon prio=10 tid=0xb6a75800 nid=0x2f9a runnable [0x00000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "Signal Dispatcher" daemon prio=10 tid=0xb6a6d400 nid=0x2f97 runnable [0x00000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "Finalizer" daemon prio=10 tid=0xb6a5e000 nid=0x2f95 in Object.wait() [0x900ad000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x9b144998> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:133) - locked <0x9b144998> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:149) at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:177) Locked ownable synchronizers: - None "Reference Handler" daemon prio=10 tid=0xb6a5cc00 nid=0x2f94 in Object.wait() [0x900fe000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x9b1449b8> (a java.lang.ref.Reference$Lock) at java.lang.Object.wait(Object.java:502) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133) - locked <0x9b1449b8> (a java.lang.ref.Reference$Lock) Locked ownable synchronizers: - None "main" prio=10 tid=0xb6a07400 nid=0x2f8e waiting on condition [0xb6bf8000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x9b1630c8> (a java.util.concurrent.locks.ReentrantLock$NonfairSync) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:838) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:871) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1201) at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:214) at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:290) at sun.awt.SunToolkit.awtLock(SunToolkit.java:264) at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:616) at jogamp.nativewindow.jawt.JAWTUtil.awtLock(JAWTUtil.java:298) at jogamp.nativewindow.jawt.JAWTUtil.lockToolkit(JAWTUtil.java:328) at jogamp.nativewindow.jawt.JAWTUtil$2.lock(JAWTUtil.java:227) at javax.media.nativewindow.DefaultGraphicsDevice.lock(DefaultGraphicsDevice.java:128) at com.jogamp.nativewindow.awt.JAWTWindow.lockSurface(JAWTWindow.java:278) at jogamp.opengl.GLDrawableImpl.lockSurface(GLDrawableImpl.java:195) at jogamp.opengl.GLDrawableImpl.setRealized(GLDrawableImpl.java:156) - locked <0x9b2aec78> (a jogamp.opengl.x11.glx.X11OnscreenGLXDrawable) at javax.media.opengl.awt.GLCanvas.validateGLDrawable(GLCanvas.java:556) at javax.media.opengl.awt.GLCanvas.display(GLCanvas.java:398) at jogamp.opengl.GLDrawableHelper.invoke(GLDrawableHelper.java:287) - locked <0x907532b8> (a java.lang.Object) at javax.media.opengl.awt.GLCanvas.invoke(GLCanvas.java:654) at com.ardor3d.framework.jogl.JoglAwtCanvas.init(JoglAwtCanvas.java:64) at com.ardor3d.framework.jogl.JoglAwtCanvas.draw(JoglAwtCanvas.java:76) at com.ardor3d.framework.FrameHandler.updateFrame(FrameHandler.java:90) at com.ardor3d.example.canvas.JoglAwtExample.main(JoglAwtExample.java:132) Locked ownable synchronizers: - <0x9b2aeb98> (a jogamp.common.util.locks.RecursiveLockImpl01Unfairish$SingleThreadSync) "VM Thread" prio=10 tid=0xb6a58c00 nid=0x2f93 runnable "VM Periodic Task Thread" prio=10 tid=0xb6a7e400 nid=0x2fa4 waiting on condition JNI global references: 3871 I use a cached GLRunnable, I cannot use our listener model in order to respect Ardor3D framework that uses its own abstraction above all OpenGL bindings. There is no shared context involved yet, each canvas has its own context. +++ LOCK 0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> +++ LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> Info: XInitThreads() called for concurrent Thread support +++ LOCK 0 <a826da, 18ed77a>[count 1 [ add. 0, orig 1], qsz 0, owner <main>, add.owner ], cur <main> +++ LOCK XR <a826da, 18ed77a>[count 2 [ add. 0, orig 2], qsz 0, owner <main>, add.owner ], cur <main> NullToolkitLock.lock() NullToolkitLock.unlock() X11ToolkitLock.lock() - native: false +++ LOCK 0 <1e29b99, 5585dc>[count 0, qsz 0, owner <NULL>], cur <main-SharedResourceRunner> +++ LOCK X0 <1e29b99, 5585dc>[count 0, qsz 0, owner <NULL>], cur <main-SharedResourceRunner> +++ LOCK 0 <a826da, 18ed77a>[count 2 [ add. 0, orig 2], qsz 0, owner <main>, add.owner main-SharedResourceRunner], cur <main-SharedResourceRunner> +++ LOCK XR <a826da, 18ed77a>[count 3 [ add. 1, orig 2], qsz 0, owner <main>, add.owner main-SharedResourceRunner], cur <main-SharedResourceRunner> ++ unlock(0): currentThread main-SharedResourceRunner, lock: <a826da, 18ed77a>[count 3 [ add. 1, orig 2], qsz 0, owner <main>, add.owner main-SharedResourceRunner] ++ unlock(X): currentThread main-SharedResourceRunner, lock: <a826da, 18ed77a>[count 3 [ add. 1, orig 2], qsz 0, owner <main>, add.owner main-SharedResourceRunner] --- LOCK XR <a826da, 18ed77a>[count 2 [ add. 0, orig 2], qsz 0, owner <main>, add.owner main-SharedResourceRunner], cur <main-SharedResourceRunner> +++ LOCK 0 <a826da, 18ed77a>[count 2 [ add. 0, orig 2], qsz 0, owner <main>, add.owner main-SharedResourceRunner], cur <main-SharedResourceRunner> +++ LOCK XR <a826da, 18ed77a>[count 3 [ add. 1, orig 2], qsz 0, owner <main>, add.owner main-SharedResourceRunner], cur <main-SharedResourceRunner> ++ unlock(0): currentThread main-SharedResourceRunner, lock: <a826da, 18ed77a>[count 3 [ add. 1, orig 2], qsz 0, owner <main>, add.owner main-SharedResourceRunner] ++ unlock(X): currentThread main-SharedResourceRunner, lock: <a826da, 18ed77a>[count 3 [ add. 1, orig 2], qsz 0, owner <main>, add.owner main-SharedResourceRunner] --- LOCK XR <a826da, 18ed77a>[count 2 [ add. 0, orig 2], qsz 0, owner <main>, add.owner main-SharedResourceRunner], cur <main-SharedResourceRunner> +++ LOCK 0 <a826da, 18ed77a>[count 2 [ add. 0, orig 2], qsz 0, owner <main>, add.owner main-SharedResourceRunner], cur <main-SharedResourceRunner> +++ LOCK XR <a826da, 18ed77a>[count 3 [ add. 1, orig 2], qsz 0, owner <main>, add.owner main-SharedResourceRunner], cur <main-SharedResourceRunner> ++ unlock(0): currentThread main-SharedResourceRunner, lock: <a826da, 18ed77a>[count 3 [ add. 1, orig 2], qsz 0, owner <main>, add.owner main-SharedResourceRunner] ++ unlock(X): currentThread main-SharedResourceRunner, lock: <a826da, 18ed77a>[count 3 [ add. 1, orig 2], qsz 0, owner <main>, add.owner main-SharedResourceRunner] --- LOCK XR <a826da, 18ed77a>[count 2 [ add. 0, orig 2], qsz 0, owner <main>, add.owner main-SharedResourceRunner], cur <main-SharedResourceRunner> +++ LOCK 0 <1f8f8c8, 952905>[count 0, qsz 0, owner <NULL>], cur <main-SharedResourceRunner> +++ LOCK X0 <1f8f8c8, 952905>[count 0, qsz 0, owner <NULL>], cur <main-SharedResourceRunner> +++ LOCK 0 <b83be0, 1631573>[count 0, qsz 0, owner <NULL>], cur <main-SharedResourceRunner> +++ LOCK X0 <b83be0, 1631573>[count 0, qsz 0, owner <NULL>], cur <main-SharedResourceRunner> X11ToolkitLock.lock() - native: false +++ LOCK 0 <1e29b99, 5585dc>[count 1, qsz 0, owner <main-SharedResourceRunner>], cur <main-SharedResourceRunner> +++ LOCK XR <1e29b99, 5585dc>[count 2, qsz 0, owner <main-SharedResourceRunner>], cur <main-SharedResourceRunner> X11ToolkitLock.unlock() - native: false --- LOCK XR <1e29b99, 5585dc>[count 1, qsz 0, owner <main-SharedResourceRunner>], cur <main-SharedResourceRunner> --- LOCK X0 <b83be0, 1631573>[count 0, qsz 0, owner <NULL>], cur <main-SharedResourceRunner>, signal any --- LOCK X0 <1f8f8c8, 952905>[count 0, qsz 0, owner <NULL>], cur <main-SharedResourceRunner>, signal any X11ToolkitLock.unlock() - native: false --- LOCK X0 <1e29b99, 5585dc>[count 0, qsz 0, owner <NULL>], cur <main-SharedResourceRunner>, signal any ++ unlock(X): currentThread main, lock: <a826da, 18ed77a>[count 2 [ add. 0, orig 2], qsz 0, owner <main>, add.owner ] --- LOCK XR <a826da, 18ed77a>[count 1 [ add. 0, orig 1], qsz 0, owner <main>, add.owner ], cur <main> ++ unlock(X): currentThread main, lock: <a826da, 18ed77a>[count 1 [ add. 0, orig 1], qsz 0, owner <main>, add.owner ] --- LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main>, signal any +++ LOCK 0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> +++ LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> ++ unlock(X): currentThread main, lock: <a826da, 18ed77a>[count 1 [ add. 0, orig 1], qsz 0, owner <main>, add.owner ] --- LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main>, signal any +++ LOCK 0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> +++ LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> ++ unlock(X): currentThread main, lock: <a826da, 18ed77a>[count 1 [ add. 0, orig 1], qsz 0, owner <main>, add.owner ] --- LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main>, signal any JAWTUtil-ToolkitLock.lock() NullToolkitLock.lock() NullToolkitLock.unlock() JAWTUtil-ToolkitLock.lock() JAWTUtil-ToolkitLock.lock() +++ LOCK 0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> +++ LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> ++ unlock(X): currentThread main, lock: <a826da, 18ed77a>[count 1 [ add. 0, orig 1], qsz 0, owner <main>, add.owner ] --- LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main>, signal any +++ LOCK 0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> +++ LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> ++ unlock(X): currentThread main, lock: <a826da, 18ed77a>[count 1 [ add. 0, orig 1], qsz 0, owner <main>, add.owner ] --- LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main>, signal any JAWTUtil-ToolkitLock.unlock() JAWTUtil-ToolkitLock.unlock() JAWTUtil-ToolkitLock.unlock() +++ LOCK 0 <4e50ee, 1a3551c>[count 0, qsz 0, owner <NULL>], cur <main> +++ LOCK X0 <4e50ee, 1a3551c>[count 0, qsz 0, owner <NULL>], cur <main> JAWTUtil-ToolkitLock.lock() JAWTUtil-ToolkitLock.lock() JAWTUtil-ToolkitLock.unlock() JAWTUtil-ToolkitLock.unlock() --- LOCK X0 <4e50ee, 1a3551c>[count 0, qsz 0, owner <NULL>], cur <main>, signal any JAWTUtil-ToolkitLock.lock() NullToolkitLock.lock() NullToolkitLock.unlock() JAWTUtil-ToolkitLock.lock() JAWTUtil-ToolkitLock.lock() +++ LOCK 0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> +++ LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> ++ unlock(X): currentThread main, lock: <a826da, 18ed77a>[count 1 [ add. 0, orig 1], qsz 0, owner <main>, add.owner ] --- LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main>, signal any +++ LOCK 0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> +++ LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> ++ unlock(X): currentThread main, lock: <a826da, 18ed77a>[count 1 [ add. 0, orig 1], qsz 0, owner <main>, add.owner ] --- LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main>, signal any JAWTUtil-ToolkitLock.unlock() JAWTUtil-ToolkitLock.unlock() JAWTUtil-ToolkitLock.unlock() +++ LOCK 0 <1cbcf91, 1a847df>[count 0, qsz 0, owner <NULL>], cur <main> +++ LOCK X0 <1cbcf91, 1a847df>[count 0, qsz 0, owner <NULL>], cur <main> JAWTUtil-ToolkitLock.lock() JAWTUtil-ToolkitLock.lock() JAWTUtil-ToolkitLock.unlock() JAWTUtil-ToolkitLock.unlock() --- LOCK X0 <1cbcf91, 1a847df>[count 0, qsz 0, owner <NULL>], cur <main>, signal any JAWTUtil-ToolkitLock.lock() NullToolkitLock.lock() NullToolkitLock.unlock() JAWTUtil-ToolkitLock.lock() JAWTUtil-ToolkitLock.lock() +++ LOCK 0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> +++ LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> ++ unlock(X): currentThread main, lock: <a826da, 18ed77a>[count 1 [ add. 0, orig 1], qsz 0, owner <main>, add.owner ] --- LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main>, signal any +++ LOCK 0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> +++ LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> ++ unlock(X): currentThread main, lock: <a826da, 18ed77a>[count 1 [ add. 0, orig 1], qsz 0, owner <main>, add.owner ] --- LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main>, signal any JAWTUtil-ToolkitLock.unlock() JAWTUtil-ToolkitLock.unlock() JAWTUtil-ToolkitLock.unlock() +++ LOCK 0 <1734b48, 537d55>[count 0, qsz 0, owner <NULL>], cur <main> +++ LOCK X0 <1734b48, 537d55>[count 0, qsz 0, owner <NULL>], cur <main> JAWTUtil-ToolkitLock.lock() JAWTUtil-ToolkitLock.lock() JAWTUtil-ToolkitLock.unlock() JAWTUtil-ToolkitLock.unlock() --- LOCK X0 <1734b48, 537d55>[count 0, qsz 0, owner <NULL>], cur <main>, signal any +++ LOCK 0 <4e50ee, 1a3551c>[count 0, qsz 0, owner <NULL>], cur <main> +++ LOCK X0 <4e50ee, 1a3551c>[count 0, qsz 0, owner <NULL>], cur <main> JAWTUtil-ToolkitLock.lock() JAWTUtil-ToolkitLock.lock() JAWTUtil-ToolkitLock.lock() +++ LOCK 0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> +++ LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> ++ unlock(X): currentThread main, lock: <a826da, 18ed77a>[count 1 [ add. 0, orig 1], qsz 0, owner <main>, add.owner ] --- LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main>, signal any +++ LOCK 0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> +++ LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main> ++ unlock(X): currentThread main, lock: <a826da, 18ed77a>[count 1 [ add. 0, orig 1], qsz 0, owner <main>, add.owner ] --- LOCK X0 <a826da, 18ed77a>[count 0 [ add. 0, orig 0], qsz 0, owner <NULL>, add.owner ], cur <main>, signal any JAWTUtil-ToolkitLock.unlock() JAWTUtil-ToolkitLock.unlock() JAWTUtil-ToolkitLock.unlock() --- LOCK X0 <4e50ee, 1a3551c>[count 0, qsz 0, owner <NULL>], cur <main>, signal any +++ LOCK 0 <1dacb2b, 15092c0>[count 0, qsz 0, owner <NULL>], cur <AWT-EventQueue-0> +++ LOCK X0 <1dacb2b, 15092c0>[count 0, qsz 0, owner <NULL>], cur <AWT-EventQueue-0> +++ LOCK 0 <4e50ee, 1a3551c>[count 0, qsz 0, owner <NULL>], cur <AWT-EventQueue-0> +++ LOCK X0 <4e50ee, 1a3551c>[count 0, qsz 0, owner <NULL>], cur <AWT-EventQueue-0> JAWTUtil-ToolkitLock.lock() +++ LOCK 0 <1dacb2b, 15092c0>[count 1, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> +++ LOCK XR <1dacb2b, 15092c0>[count 2, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> +++ LOCK 0 <4e50ee, 1a3551c>[count 1, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> +++ LOCK XR <4e50ee, 1a3551c>[count 2, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> --- LOCK XR <4e50ee, 1a3551c>[count 1, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> --- LOCK XR <1dacb2b, 15092c0>[count 1, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> +++ LOCK 0 <1dacb2b, 15092c0>[count 1, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> +++ LOCK XR <1dacb2b, 15092c0>[count 2, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> +++ LOCK 0 <4e50ee, 1a3551c>[count 1, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> +++ LOCK XR <4e50ee, 1a3551c>[count 2, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> +++ LOCK 0 <1dacb2b, 15092c0>[count 2, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> +++ LOCK XR <1dacb2b, 15092c0>[count 3, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> +++ LOCK 0 <4e50ee, 1a3551c>[count 2, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> +++ LOCK XR <4e50ee, 1a3551c>[count 3, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> +++ LOCK 0 <4e50ee, 1a3551c>[count 3, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> +++ LOCK XR <4e50ee, 1a3551c>[count 4, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> --- LOCK XR <4e50ee, 1a3551c>[count 3, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> --- LOCK XR <4e50ee, 1a3551c>[count 2, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> --- LOCK XR <1dacb2b, 15092c0>[count 2, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> --- LOCK XR <4e50ee, 1a3551c>[count 1, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> --- LOCK XR <1dacb2b, 15092c0>[count 1, qsz 0, owner <AWT-EventQueue-0>], cur <AWT-EventQueue-0> +++ LOCK 0 <1cbcf91, 1a847df>[count 0, qsz 0, owner <NULL>], cur <main> +++ LOCK X0 <1cbcf91, 1a847df>[count 0, qsz 0, owner <NULL>], cur <main> JAWTUtil-ToolkitLock.lock() 'AWT-EventQueue-0' holds - 0x9b1630c8 (AWTTreeLock). - 0x9b2ab790 (jogl lock) - 0x9b2ac370 (jogl lock) 'main' waits for it - it tries to lock AWT due to setRealized(true). 'main' holds: - 0x9b2aeb98 (jogl lock) +++ IMHO this is a starvation. AWT-EDT-0 doesn't release the AWTTreeLock, nor the jogl locks. Why ? Maybe you didn't ensure releasing the lock like lock(); try { do-some-thing; } finally { unlock(); } Maybe one of your GLRunnables you execute on the AWT-EDT throws an exception and w/o the unlock in the finally clause, starvation. Just a guess. +++ Also your 'canvas' impl. call setRealized(true) not from the AWT-EDT, as we do it. This is a possible source of a deadlock .. but I am not so sure here, since it looks more like a starvation (See above). But try it - it's always good to be consistent, i.e. call all AWT resource utilization from the AWT-EDT. I tried to call requestFocus and setVisible(true) directly in the GLRunnable but it did not solve my problem. Hi This bug is reproducible only under GNU Linux, not under Microsoft Windows: http://www.ardor3d.com/forums/viewtopic.php?f=11&t=274&start=130#p15724 If you want to reproduce this bug (until I provide a smaller test case), please install Ardor3D and the renderer based on JOGL 2.0 by following these instructions: http://gouessej.wordpress.com/2011/09/18/le-moteur-3d-ardor3d-fonctionne-desormais-avec-jogl-2-the-3d-engine-ardor3d-now-works-with-jogl-2/ Finally, run JoglAwtExample. Sorry for the long delay .. reproduced with ardor3d's trunk and your svn repo. Triaging now... Created attachment 348 [details]
Ardor3D JOGL2 Patch Fix GLContext makeCurrent/release imbalance / commented-out workaround for old JOGL bug
Ardor3D JOGL2 Patch Fix:
- GLContext makeCurrent/release imbalance
- Commented-out workaround for old JOGL bug
as fixed in JOGL commit c066dc997646643a98c35b7c70183930284544d1
- Update to Ardor3D-core SVN r1853
- Eclipse .classpath: Added gluegen & jogl source attachment
(In reply to comment #14) > Created attachment 348 [details] > Ardor3D JOGL2 Patch Fix GLContext makeCurrent/release imbalance / commented-out > workaround for old JOGL bug > > Ardor3D JOGL2 Patch Fix: > - GLContext makeCurrent/release imbalance The imbalance throws an exception in JOGL (at exit). You were doing more makeCurrent() calls then release(), where destroy() shall be either done w/o holding the context or while holding it once. Further recursive locking at destroy will fail-fast to help developer to fix this bug. > > - Commented-out workaround for old JOGL bug > as fixed in JOGL commit c066dc997646643a98c35b7c70183930284544d1 Since we don't produce builds until end of May, you may want to check JoglAwtCanvas.java line 59-72 in the patched file. Instead of calling setVisible(true) directly, which will be valid w/ the latest JOGL fix, you need to uncomment this call and use the commented-out variant which issues the call on the AWT-EDT including a forced display(). > > - Update to Ardor3D-core SVN r1853 > > - Eclipse .classpath: Added gluegen & jogl source attachment Works fine here now. Hi Thank you so much. I confirm your fixes work fine. I have committed them, I will remove one of them when the nightly builds are available. It seems that commit 4b5a0f6557d7152ec770bc13ad3c494449de0529 caused a regression, where validateGL()'s drawable.setRealize(true) might not get called from the AWT-EDT. Created attachment 370 [details]
partial revert of commit 4b5a0f6557d7152ec770bc13ad3c494449de0529
partial revert of commit 4b5a0f6557d7152ec770bc13ad3c494449de0529
Pls test Attachment 370 [details]
The GLCanvas is no more realized when calling setVisible(true) even though I do it from the AWT EDT. If I call invoke(true, GLRunnable) just after, it returns false and the drawable is not null but not realized. I have to test your suggestion. (In reply to comment #20) > The GLCanvas is no more realized when calling setVisible(true) even though I do > it from the AWT EDT. If I call invoke(true, GLRunnable) just after, it returns > false and the drawable is not null but not realized. I have to test your > suggestion. Well, realization of the AWT component @ setVisible(true) is lazy (as we know), hence we 'poll' it's validity. This was same w/ pre 4b5a0f6557d7152ec770bc13ad3c494449de0529 The patch partially brings back the flow of validateGLDrawable issuuing setRealized(true) on the AWT-EDT. Don't really know whether this is the cause or not. Again, if you can create a 'reliable' unit test to demonstrate the bug it would be great. Maybe it is enough to call display() from a non AWT-EDT before and after setVisible(true) ? (In reply to comment #21) > (In reply to comment #20) > > The GLCanvas is no more realized when calling setVisible(true) even though I do > > it from the AWT EDT. If I call invoke(true, GLRunnable) just after, it returns > > false and the drawable is not null but not realized. I have to test your > > suggestion. > > Well, realization of the AWT component @ setVisible(true) is lazy (as we know), > hence we 'poll' it's validity. This was same w/ pre > 4b5a0f6557d7152ec770bc13ad3c494449de0529 > > The patch partially brings back the flow of validateGLDrawable > issuuing setRealized(true) on the AWT-EDT. Don't really know whether this is > the cause or not. > > Again, if you can create a 'reliable' unit test to demonstrate the bug it would > be great. > Maybe it is enough to call display() from a non AWT-EDT before and after > setVisible(true) ? Your change does not solve the problem, I have just tested. Yes I would like to write a unit test but it is a bit difficult because Ardor3D uses an elaborated framework whereas a unit test should be as rudimentary as possible. (In reply to comment #21) > Again, if you can create a 'reliable' unit test to demonstrate the bug it would > be great. Just use TestBug551AWT and add the following code into the line 102: System.out.println(glCanvas[0].getDelegatedDrawable().isRealized()); It returned true in RC9, it returns false in RC10. Calling display() to realize the drawable seems to be needed only with AWT GLCanvas, neither with NewtCanvasAWT nor with GLWindow. See <http://jogamp.org/git/?p=jogl.git;a=commit;h=a3cb6bb14f410f67fccf5ccd4cd7ecc66f448389> I have added the size validation patch .. in this one as well, as reported here: <http://forum.jogamp.org/InternalError-in-GLDrawableHelper-on-OSX-10-8-td4026337.html> Pls also read the new unit test for clarification. (In reply to comment #24) > See > <http://jogamp.org/git/?p=jogl.git;a=commit;h=a3cb6bb14f410f67fccf5ccd4cd7ecc66f448389> > > I have added the size validation patch .. in this one as well, as reported > here: > > <http://forum.jogamp.org/InternalError-in-GLDrawableHelper-on-OSX-10-8-td4026337.html> > > Pls also read the new unit test for clarification. Ok I'm going to test it immediately. You were not forced to remove the null check in setRealizedOnEDTAction. (In reply to comment #25) > You were not forced to remove the null > check in setRealizedOnEDTAction. Well, we claim the lock, hence assuming null and size checks would be redundant. But earmarking it .. (In reply to comment #26) > (In reply to comment #25) > > You were not forced to remove the null > > check in setRealizedOnEDTAction. > > Well, we claim the lock, hence assuming null and size checks would be > redundant. > But earmarking it .. Ok :) It would be fine to have an autobuild with this fix so that I can remove the kludge from the Ardor3D renderer based on JOGL 2.0. (In reply to comment #27) > > It would be fine to have an autobuild with this fix so that I can remove the > kludge from the Ardor3D renderer based on JOGL 2.0. Will happen today, just testing another FBO 'hack', regarding the dummySurface. (In reply to comment #28) > (In reply to comment #27) > > > > It would be fine to have an autobuild with this fix so that I can remove the > > kludge from the Ardor3D renderer based on JOGL 2.0. > > Will happen today, just testing another FBO 'hack', regarding the dummySurface. It works perfectly :) Thanks for the fix and the unit test. |