[2.0 RC3] PBuffer uses awtlock during display

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

[2.0 RC3] PBuffer uses awtlock during display

Tovi
Hey,

Just a quick question, cause I'm kindof stuck with this.

I'm trying to do some onscreen rendering while at the same time also do some offscreen rendering in a separate thread (using GLPBuffer). The problem I noticed is that the GLPBuffer seems to call Suntoolkit.awtlock(). This has the potential for deadlocks, as the onscreen view features some Swing components that also lock awt.

Is there a way to disable the locking of AWT for PBuffers? I noticed there is an exception for headless mode, but this is not an option for me.

I also found some documentation that said that "-Dnativewindow.nolocking=true" would force the toolkit lock to be disabled, but I didn't find any reference to this in the code, so I'm guessing this is no longer valid?

As a quick test I tried uncommenting the part where the lock is taken (JAWTUtil.awtLock() and JAWTUtil.awtUnlock()), and everything seemed to work just fine.

So my questions are:

- Why enforce an awtlock on PBuffers?
- Wouldn't it be better to have a separate static lock for nativewindow so as to prevent deadlocks in multithreading environments?
- Is there any way currently to disable awt locking without modifying the source code? (I'm trying to work with binaries as much as possible, since managing sources can be tedious over time)

If needed, I would be up for adapting the code to suit my needs, and let you determine whether you want to insert it to your code ;)

Please also let me know if I'm missing something, or doing something wrong.

Thx in advance,
Tovi
Reply | Threaded
Open this post in threaded view
|

Re: [2.0 RC3] PBuffer uses awtlock during display

Sven Gothel
Administrator
On Wednesday, September 21, 2011 04:30:06 PM Tovi [via jogamp] wrote:

>
> Hey,
>
> Just a quick question, cause I'm kindof stuck with this.
>
> I'm trying to do some onscreen rendering while at the same time also do some
> offscreen rendering in a separate thread (using GLPBuffer). The problem I
> noticed is that the GLPBuffer seems to call Suntoolkit.awtlock(). This has
> the potential for deadlocks, as the onscreen view features some Swing
> components that also lock awt.

I see. Indeed looks like the wrong choice of the ToolkitLock
for the underlying device in this case.

First, try to issue 'GLProfile.initSingleton(true)'
ASAP, ie in your applications static block.

This will influence the underlying lock mechanism,
ie if called it sets NativeWindowFactory's requiresToolkitLock:=false,
otherwise true.

NativeWindowFactory.getDefaultToolkitLock(..)
  If requiresToolkitLock()==true and if AWT is available and X11,
  we simple choose the JAWTToolkitLock.

NativeWindowFactory.createDefaultToolkitLock(..)
  Same logic plus choosing the X11 variant of the lock.


Why do we do this ?
In case the AbstractGraphicsDevice (display handle, etc)
is being used in conjunction with AWT and we don't
use X11 in a thread save manner 'GLProfile.initSingleton(true)',
we need to lock the native display.

We could avoid this behavior in cases where it is guaranteed
that the display is not being used w/ AWT.
I guess this is true in this case and I will look into it.
Thank you.

In the meantime, please just call 'GLProfile.initSingleton(true)',
which should solve your problem when you can be sure your application
is the 1st user of the native windowing system (no applet, no IDE plugin .. etc).

If you could provide me with a simple test case
it would be much more safe to produce and verify a solution.
Best, if you just copy one of our unit tests, rename it, change it
to fit your point. Thank you.


>
> Is there a way to disable the locking of AWT for PBuffers? I noticed there
> is an exception for headless mode, but this is not an option for me.
>
> I also found some documentation that said that
> "-Dnativewindow.nolocking=true" would force the toolkit lock to be disabled,
> but I didn't find any reference to this in the code, so I'm guessing this is
> no longer valid?
yup

>
> As a quick test I tried uncommenting the part where the lock is taken
> (JAWTUtil.awtLock() and JAWTUtil.awtUnlock()), and everything seemed to work
> just fine.

ok

>
> So my questions are:
>
> - Why enforce an awtlock on PBuffers?

as described lenghtly above, maybe just the wrong pick of the ToolkitLock.

> - Wouldn't it be better to have a separate static lock for nativewindow so
> as to prevent deadlocks in multithreading environments?

The whole ToolkitLock usage is very sensible when using AWT,
so we have to be carefull to not bring down the whole AWT :)

So we have to make this decision case by case.

> - Is there any way currently to disable awt locking without modifying the
> source code? (I'm trying to work with binaries as much as possible, since
> managing sources can be tedious over time)

see above, GLProfile.initSingleton(true)

>
> If needed, I would be up for adapting the code to suit my needs, and let you
> determine whether you want to insert it to your code ;)

sure. A test case would be best first.
Then let me think and test about a safe unlocked path.

>
> Please also let me know if I'm missing something, or doing something wrong.

You hit the nail on the head in the coffin :)

Good job, thx.

Waiting for your test case.


>
> Thx in advance,
> Tovi

Reply | Threaded
Open this post in threaded view
|

Re: [2.0 RC3] PBuffer uses awtlock during display

Sven Gothel
Administrator
In reply to this post by Tovi
On Wednesday, September 21, 2011 04:30:06 PM Tovi [via jogamp] wrote:
>
> Hey,
>
> Just a quick question, cause I'm kindof stuck with this.
>
> I'm trying to do some onscreen rendering while at the same time also do some
> offscreen rendering in a separate thread (using GLPBuffer). The problem I
> noticed is that the GLPBuffer seems to call Suntoolkit.awtlock().

I actually fail to see GLPBuffer displayImpl() calling display.lock(),
which would end up in such JAWTUtil lock call.
Only at creation the display.lock() is being issued as far as I can see.

So please provide a test case to reproduce.
Oh .. a stack trace would be very usefull as well. Thank you.

~Sven
Reply | Threaded
Open this post in threaded view
|

Re: [2.0 RC3] PBuffer uses awtlock during display

Tovi
Hey Sven,

Thanks for the fast reply. Here's the stack trace on how GLDrawable gets to AWTLock:

  java.lang.Thread.State: WAITING
          at sun.misc.Unsafe.park(Unsafe.java:-1)
          at java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
          at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:811)
          at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:842)
          at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1178)
          at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:186)
          at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:262)
          at sun.awt.SunToolkit.awtLock(SunToolkit.java:236)
          at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source:-1)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
          at java.lang.reflect.Method.invoke(Method.java:597)
          at jogamp.nativewindow.jawt.JAWTUtil.awtLock(JAWTUtil.java:195)
          at jogamp.nativewindow.jawt.JAWTUtil.lockToolkit(JAWTUtil.java:224)
          at jogamp.nativewindow.jawt.x11.X11JAWTToolkitLock.lock(X11JAWTToolkitLock.java:51)
          at javax.media.nativewindow.DefaultGraphicsDevice.lock(DefaultGraphicsDevice.java:128)
          at javax.media.nativewindow.ProxySurface.lockSurface(ProxySurface.java:94)
          at jogamp.opengl.GLDrawableImpl.lockSurface(GLDrawableImpl.java:186)
          at jogamp.opengl.GLContextImpl.makeCurrentLocking(GLContextImpl.java:435)
          at jogamp.opengl.GLContextImpl.makeCurrent(GLContextImpl.java:388)
          at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:328)
          at jogamp.opengl.GLPbufferImpl.invokeGL(GLPbufferImpl.java:289)
          at jogamp.opengl.GLPbufferImpl.display(GLPbufferImpl.java:148)

I've tried your suggestion, and it seems to fix my specific test, but in more general cases it sometimes causes a JVM crash. I'm still investigating the exact cause for this, but I'm assuming that if locking is disabled completely, a crash can occur because of concurrency? Is there a way to lock something else (some static object) instead of awt?

In any case, thanks again for the fast reply, for now I'll try to work with GLProfile.initSingleton and see if I can fix the JVM crash it seems to cause sometimes.

If I get some time I'll examine your tests and send you a test to reproduce the issue. :)

Regards,
Tovi
Reply | Threaded
Open this post in threaded view
|

Re: [2.0 RC3] PBuffer uses awtlock during display

Tovi
Sven,

Is there any way to detect whether a call to GLProfile.initSingleton(true) will crash the JVM or block it? i.e. is there a set of conditions that will cause GLProfile.initSingleton(true) to crash my application. I'm asking because in my application I can't always be sure that I can call this as the first line.

I'm trying to find a way to detect whether or not a call to GLProfile.initSingleton(true) will crash the JVM, so I can display an error message instead.

I really can't make out when it will or won't happen. Some small examples will not crash it, while others will.

For instance, the following code will not crash it:

JFrame jframe = new JFrame()
jFrame.setVisible(true)
GLProfile.initSingleton(true)

but for some reason this will:

Frame jframe = new Frame()
jFrame.setVisible(true)
GLProfile.initSingleton(true)

Also, only in Linux (not windows), as far as I can tell. But still strange because JFrame extends from Frame.

What exactly is the reason that GLProfile.initSingleton(true) should be called before any other AWT call?
Reply | Threaded
Open this post in threaded view
|

Re: [2.0 RC3] PBuffer uses awtlock during display

Sven Gothel
Administrator
On Wednesday, September 28, 2011 05:12:53 PM Tovi [via jogamp] wrote:
>
> Sven,
>
> Is there any way to detect whether a call to GLProfile.initSingleton(true)
> will crash the JVM or block it? i.e. is there a set of conditions that will
> cause GLProfile.initSingleton(true). I'm asking because in my application I
> can't always be sure that I can call this as the first line.
>
If in doubt .. pass false.

Still waiting for the test case :)

IE we should fix this bug anyways
and I don't see the point where PBuffer locks anything.

Reply | Threaded
Open this post in threaded view
|

Re: [2.0 RC3] PBuffer uses awtlock during display

Tovi
Sven, I copied TestGearsAWT and modified it to demonstrate the issue with PBuffer deadlocks when AWT is used.

I also don't see the point of locking AWT for PBuffers, which are used for offscreen rendering. I believe this test should succeed without a call to GLProfile.initSingleton(true). (though right now it doesn't, and it will timeout after 10 seconds). The test is very artificial, but it proves a point: You perform a task on a non-awt thread, while also keeping an awt lock. This should not lock the application.

Regards,
Tovi




import com.jogamp.opengl.test.junit.util.UITestCase;
import org.junit.*;
import sun.awt.SunToolkit;

import javax.media.opengl.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestPBufferDeadLock extends UITestCase {
  static GLProfile glp;
  static int width, height;
  private ExecutorService fSingleThreadExecutorService;

  @BeforeClass
  public static void initClass() {
    glp = GLProfile.getDefault();
    Assert.assertNotNull( glp );
    width = 512;
    height = 512;
  }

  @AfterClass
  public static void releaseClass() {
  }

  @Override @Before
  public void setUp() {
    super.setUp();
    fSingleThreadExecutorService = Executors.newFixedThreadPool( 1 );
  }

  protected void runTestGL( GLCapabilities caps ) throws InterruptedException {
    final GLPbuffer pbuffer = GLDrawableFactory.getFactory( GLProfile.get( "GL2" ) ).createGLPbuffer(
        null,
        caps,
        new DefaultGLCapabilitiesChooser(),
        512,
        512,
        null
    );

    final boolean[] done = {false};
    Runnable runnable = new Runnable() {
      public void run() {
        pbuffer.display();
        done[ 0 ] = true;
      }
    };
    try {
      SunToolkit.awtLock();
      fSingleThreadExecutorService.execute( runnable );
      while ( !done[ 0 ] ) {
        try {
          Thread.sleep( 100 );
        }
        catch ( InterruptedException e ) {
          Assert.fail( "Failed to sleep" );
        }
      }

    }
    finally {
      SunToolkit.awtUnlock();
    }
  }

  @Test(timeout = 10000) //10 second timeout
  public void testDeadlock() throws InterruptedException {
    GLCapabilities caps = new GLCapabilities( glp );
    runTestGL( caps );
  }

  static long duration = 500; // ms

  public static void main( String args[] ) {
    for ( int i = 0; i < args.length; i++ ) {
      if ( args[ i ].equals( "-time" ) ) {
        i++;
        try {
          duration = Integer.parseInt( args[ i ] );
        }
        catch ( Exception ex ) {
          ex.printStackTrace();
        }
      }
    }
    org.junit.runner.JUnitCore.main( TestPBufferDeadLock.class.getName() );
  }
}
Reply | Threaded
Open this post in threaded view
|

Re: [2.0 RC3] PBuffer uses awtlock during display

Tovi
In reply to this post by Sven Gothel
By the way, you mentioned this is a bug and should be fixed. Is there a bugtracker ticket that was created for this, that I could follow?

Also, is there any way I could help to help solve this bug?
Reply | Threaded
Open this post in threaded view
|

Re: [2.0 RC3] PBuffer uses awtlock during display

Sven Gothel
Administrator
On Monday, October 03, 2011 10:21:02 AM Tovi [via jogamp] wrote:
>
> By the way, you mentioned this is a bug and should be fixed.
Thank you for your code snippet.
Later I will have time to take care of it.

> Is there a
> bugtracker ticket that was created for this, that I could follow?
Of course.

https://jogamp.org/bugzilla/

Create an account .. add the bug. Assigne me and you.

>
> Also, is there any way I could help to help solve this bug?
You already did the 1st important step I guess, ie. sending the code
which reproduces it (I hope - haven't tested it yet).

- Next step is to reproduce it.
- Then analyze and fix it.

Feel free to do it, sure.
We can discuss it (analysis, fix, ..) in bugzilla.

~Sven
Reply | Threaded
Open this post in threaded view
|

Re: [2.0 RC3] PBuffer uses awtlock during display

Tovi
I have created a bug report here, as well as a (first) proposed solution and patch. Check it out here:

https://jogamp.org/bugzilla/show_bug.cgi?id=519

Regards,
Tovi
Reply | Threaded
Open this post in threaded view
|

Re: [2.0 RC3] PBuffer uses awtlock during display

gregirvine
In reply to this post by Tovi
Although we're still using JOGL 1.1.1 we're seeing a nearly identical issue when running multithreaded mode - opengl.1thread=false.
It's not related to PBuffers but to the GLCanvas.
Somewhere in the JOGL thread during a display run an AWT lock is performed and when we get a mouse click that results in a popup being opened at the same time we end up with a deadlock.
From what I've read in this discussion and in the bugzilla bug report I'm guessing the lock is happening in the makeCurrent() method called during invokeGL().
We do not see this problem on Windows but only on Linux.

======================================
"Timer-8" Id=106 BLOCKED on <myclass>@7d185d owned by "AWT-EventQueue-0" Id=34
...
com.sun.opengl.impl.GLDrawableHelper.display(GLDrawableHelper.java:78)
javax.media.opengl.GLCanvas$DisplayAction.run(GLCanvas.java:435)
com.sun.opengl.impl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:194)
javax.media.opengl.GLCanvas.maybeDoSingleThreadedWorkaround(GLCanvas.java:412)
javax.media.opengl.GLCanvas.display(GLCanvas.java:244)
com.sun.opengl.util.Animator.display(Animator.java:144)
com.sun.opengl.util.FPSAnimator$1.run(FPSAnimator.java:95)
java.util.TimerThread.mainLoop(Timer.java:512)
java.util.TimerThread.run(Timer.java:462)


"AWT-EventQueue-0" Id=34 WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@1a02ee9 owned by "Timer-8" Id=106
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:811)
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:842)
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1178)
java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:186)
java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:262)
sun.awt.SunToolkit.awtLock(SunToolkit.java:236)
sun.awt.X11.XWindow.getLocationOnScreen(XWindow.java:1329)
java.awt.Component.getLocationOnScreen_NoTreeLock(Component.java:1939)
java.awt.Component.getLocationOnScreen(Component.java:1917)
javax.swing.JPopupMenu.show(JPopupMenu.java:887)
...


======================================
Upgrading to JOGL2 isn't a simple matter given the project constraints, but do you think the changes made so far would resolve the issue above?
Are the changes easily imported into the jogl1.1.1 base code if we went down that path instead?

Thanks.
Reply | Threaded
Open this post in threaded view
|

Re: [2.0 RC3] PBuffer uses awtlock during display

gregirvine
Note, if I use the -Djogl.GLContext.optimize flag i don't see the deadlocks when opening the popups for example, but I do get a core dump when I resize another canvas.

Stack: [0xa5490000,0xa5558000],  sp=0xa5556430,  free space=319a5555db4k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [libGLcore.so.1+0xa6ffd4]

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  com.sun.opengl.impl.x11.GLX.glXSwapBuffers(JJ)V+0
j  com.sun.opengl.impl.x11.X11OnscreenGLDrawable.swapBuffers()V+38
j  com.sun.opengl.impl.GLDrawableHelper.invokeGL(Ljavax/media/opengl/GLDrawable;Ljavax/media/opengl/GLContext;Ljava/lang/Runnable;Ljava/lang/Runnable;)V+435
j  javax.media.opengl.GLCanvas.maybeDoSingleThreadedWorkaround(Ljava/lang/Runnable;Ljava/lang/Runnable;)V+36
j  javax.media.opengl.GLCanvas.display()V+9
j  com.sun.opengl.util.Animator.display()V+46
j  com.sun.opengl.util.FPSAnimator$1.run()V+4
j  java.util.TimerThread.mainLoop()V+221
j  java.util.TimerThread.run()V+1
v  ~StubRoutines::call_stub

Reply | Threaded
Open this post in threaded view
|

Re: [2.0 RC3] PBuffer uses awtlock during display

Sven Gothel
Administrator
In reply to this post by gregirvine
On 02/03/2012 05:55 AM, gregirvine [via jogamp] wrote:

>
>
> Although we're still using JOGL 1.1.1 we're seeing a nearly identical issue
> when running multithreaded mode - opengl.1thread=false.
> It's not related to PBuffers but to the GLCanvas.
> Somewhere in the JOGL thread during a display run an AWT lock is performed
> and when we get a mouse click that results in a popup being opened at the
> same time we end up with a deadlock.
>>From what I've read in this discussion and in the bugzilla bug report I'm
> guessing the lock is happening in the makeCurrent() method called during
> invokeGL().
> We do not see this problem on Windows but only on Linux.
The original issue is solved in JOGL[2].

We don't support JOGL[1] anymore.

If you can reproduce the bug with current JOGL[2]
pls post a proper bugreport - thank you.

~Sven

>
> ======================================
> "Timer-8" Id=106 BLOCKED on <myclass>@7d185d owned by "AWT-EventQueue-0"
> Id=34
> ...
> com.sun.opengl.impl.GLDrawableHelper.display(GLDrawableHelper.java:78)
> javax.media.opengl.GLCanvas$DisplayAction.run(GLCanvas.java:435)
> com.sun.opengl.impl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:194)
> javax.media.opengl.GLCanvas.maybeDoSingleThreadedWorkaround(GLCanvas.java:412)
> javax.media.opengl.GLCanvas.display(GLCanvas.java:244)
> com.sun.opengl.util.Animator.display(Animator.java:144)
> com.sun.opengl.util.FPSAnimator$1.run(FPSAnimator.java:95)
> java.util.TimerThread.mainLoop(Timer.java:512)
> java.util.TimerThread.run(Timer.java:462)
>
>
> "AWT-EventQueue-0" Id=34 WAITING on
> java.util.concurrent.locks.ReentrantLock$NonfairSync@1a02ee9 owned by
> "Timer-8" Id=106
> sun.misc.Unsafe.park(Native Method)
> java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
> java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:811)
> java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:842)
> java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1178)
> java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:186)
> java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:262)
> sun.awt.SunToolkit.awtLock(SunToolkit.java:236)
> sun.awt.X11.XWindow.getLocationOnScreen(XWindow.java:1329)
> java.awt.Component.getLocationOnScreen_NoTreeLock(Component.java:1939)
> java.awt.Component.getLocationOnScreen(Component.java:1917)
> javax.swing.JPopupMenu.show(JPopupMenu.java:887)
> ...
>
>
> ======================================
> Upgrading to JOGL2 isn't a simple matter given the project constraints, but
> do you think the changes made so far would resolve the issue above?
> Are the changes easily imported into the jogl1.1.1 base code if we went down
> that path instead?
>
> Thanks.


signature.asc (910 bytes) Download Attachment