PDA

View Full Version : Hang in wglDeleteContext in dtor



Geetha Priya
04-28-2017, 04:42 AM
Hi All,

Our Application UI hangs on exit, and the call stack obtained points to wglDeleteContext.
This issue is seen while using hardware rendering (NVIDIA Driver OpenGL 4.1.0 ).

When software rendering (OpenGL 1.1.0) is used, application exit is smooth.

What could be the cause for hang on deleting the rendering context.?

Below is the order of deleting context:

wglMakeCurrent( hdc , hglrc)
delete the texture
wglMakeCurrent( 0, 0 );
glFinish();
wglDeleteContext( hglrc);

Below is the opengl call stack of hang:

0ae1c1a0 62b2c36f 37cf6070 3fc00000 0ae1c1c4 nvoglv32!DrvSetPixelFormat+0xce7
0ae1c1b0 62b32289 00031a62 f2011bdc 37c52e98 nvoglv32!DrvSetPixelFormat+0x1bff
0ae1c1c4 629efa8e 37cf53e4 00000000 00000000 nvoglv32!DrvSetPixelFormat+0x7b19
0ae1c1e0 62a18d3a 3fc00000 37c52e98 00000000 nvoglv32+0x6ffa8e
0ae1c1fc 623e9981 3fc00000 39db3f70 00000001 nvoglv32+0x728d3a
0ae1c224 629f2bdd 3fc00000 39db3f70 00000000 nvoglv32+0xf9981
0ae1c254 629e98e9 3fc00000 00000000 3fc00000 nvoglv32+0x702bdd
0ae1c268 62b77430 3fc00000 00000000 39e60b50 nvoglv32+0x6f98e9
0ae1c280 62b1b82f 3fc00000 0ae1c2a4 62b2826d nvoglv32!DrvPresentBuffers+0x26b20
0ae1c28c 62b2826d 3fc00000 37c0f798 fff20138 nvoglv32+0x82b82f
0ae1c2a4 6ad5b97c 0000000e 0a630aa8 3e458f78 nvoglv32!DrvDeleteContext+0x1bd
0ae1c2c0 6a11c9af 0000000d 64ce00c9 0a630aa8 opengl32!wglDeleteContext+0x58

Thanks.

Dark Photon
04-28-2017, 06:43 AM
Well the first thing I notice is that you're calling glFinish() after you drop your GL context (wglMakeCurrent(0,0)). You need to swap those two.

The second thing I see is that your NVidia GL driver is trying to present buffers (e.g. process a swap buffers) inside of the context deletion. It could be when you delete a context it tries to "catch up" on all the queued work for that context that hasn't been executed yet. Or it could be that the glFinish() might have actually been queued (undefined behavior) and is triggering that. Not sure.

In any case, what I'd suggest to try and fix that is to call glFinish() before dropping your context (wglMakeCurrent(0,0)), which is what I suggested above.

Geetha Priya
04-28-2017, 09:27 AM
Thanks for the reply. Adding glfinish doesn't solve the problem. We even tried adding after every line but it doesn't help.

mhagain
04-28-2017, 10:28 AM
A probable cause is cleaning up GPU-allocated objects such as textures, buffers, etc. Since you say you're also using the software GL 1.1 implementation I'm going to assume that you haven't created any buffer objects, but I would be interested in knowing how many textures you have created, and if you've created any display lists (and if so, how many).

I know you say that you have a "delete the texture" operation in there, but glDeleteTextures is not actually specified to free memory: all that it is required to do is make the texture name(s) available for reuse by a subsequent call to glGenTextures. A previous time I saw similar behaviour it was caused by erroneously creating new textures (or other objects) every frame but never destroying them, resulting in a huge number of objects to actually be destroyed during context shutdown.

mhagain
04-28-2017, 02:09 PM
The other thing that occurs to me - you mentioned this happens in a destructor, so I am assuming that you're using C++ - are you absolutely certain about when your destructors run (and the order they run in)?

Dark Photon
04-28-2017, 06:32 PM
Related, and possibly useful:
* Platform specifics: Windows#When do I destroy the GL_context? (https://www.khronos.org/opengl/wiki/Platform_specifics:_Windows#When_do_I_destroy_the_ GL_context.3F) (OpenGL wiki)

Also, you might check for GL errors while your GL context is current, and also check for failure from your wglMakeCurrent() calls. That is, make sure everything looks ok up until your wglDeleteContext call.

Geetha Priya
05-02-2017, 04:39 AM
Thanks for the suggestions.

GetLastError gives GL_NO_ERROR. One strange thing this, when we enable traces for logging or debug the application, issue does not occur.

So, is there something to do with time as debug/traces puts some delay. And in the meantime, wgldeletecontext does the unfinished jobs.

Geetha Priya
05-03-2017, 04:06 AM
When sleep is added before context deletion, issue does not occur.

::glFinish();
Sleep(1000);
::wglMakeCurrent( 0, 0 );
::wglDeleteContext( hGlrc );

Is it correct to add sleep().?
Is there any way to identify if all the jobs are completed before context deletion.

Silence
05-03-2017, 05:22 AM
sleep won't guarantee that you'll have the same behavior on all the machines your program will run on. It might also stop to work on that machine for some other reasons.

I had a similar issue. This was related to FBOs not well used (read and write buffers were still bound to deleted FBOs). So, I would more go for something as mhagain told. So, it might be time for you to tell here what do you do in your program.

Silence
05-03-2017, 05:24 AM
GetLastError gives GL_NO_ERROR.

GetLastError seems to be a Windows function. This is not related to OpenGL at all.

Dark Photon
05-03-2017, 06:05 AM
GetLastError gives GL_NO_ERROR.

Silence already caught this. What I was suggesting was something like this:


#include <assert.h>
...
BOOL res = wglMakeCurrent( hdc , hglrc)
assert( res );
delete the texture
assert( glGetError() == GL_NO_ERROR );
glFinish();
assert( glGetError() == GL_NO_ERROR );
res = wglMakeCurrent( 0, 0 );
assert( res );
res = wglDeleteContext( hglrc);
assert( res );



...in the meantime, wgldeletecontext does the unfinished jobs. ...
... When sleep is added before context deletion, issue does not occur.


::glFinish();
Sleep(1000);


This in combination with your statement that glFinish() alone doesn't cut it suggests to me that the driver may not be waiting until pending work is complete to return from glFinish(). That's concerning.

However, why are you making your GL context current right before deleting a texture? What was it not already active? Are you doing something with swapping GL contexts on the same thread, or sharing the same context across multiple threads? If so, it's more likely that something you're doing with GL across multiple threads may be causing this problem.