dxgsg9 crash on exit

I found another DX crash on exit, I isolated the call that causes it to crash (on exit). It’s:

shadowBuffer = window->get_graphics_output()->make_texture_buffer("ShadowBuffer", 256, 256);

Debugger drops me at:

free_vbuffer ( );

Call stack:

>	libpandadx9.dll!DXVertexBufferContext9::~DXVertexBufferContext9()  Line 283 + 0x7 bytes	C++
 	libpandadx9.dll!DXVertexBufferContext9::`vector deleting destructor'()  + 0x41 bytes	C++
 	libpanda.dll!PreparedGraphicsObjects::begin_frame(GraphicsStateGuardianBase * gsg=0x00316f9c, Thread * current_thread=0x00311044)  Line 1250 + 0xd bytes	C++
 	libpanda.dll!GraphicsStateGuardian::close_gsg()  Line 2417	C++
 	libpandadx9.dll!DXGraphicsStateGuardian9::close_gsg()  Line 4176	C++
 	libpanda.dll!GraphicsPipe::close_gsg(GraphicsStateGuardian * gsg=0x00316f9c)  Line 119	C++
 	libpanda.dll!GraphicsEngine::WindowRenderer::do_close(GraphicsEngine * engine=0x0031591c, Thread * current_thread=0x00311044)  Line 2470	C++
 	libpanda.dll!GraphicsEngine::remove_all_windows()  Line 548	C++
 	libpanda.dll!GraphicsEngine::~GraphicsEngine()  Line 167	C++
 	libpanda.dll!GraphicsEngine::`vector deleting destructor'()  + 0x41 bytes	C++
 	libpanda.dll!`dynamic atexit destructor for 'GraphicsEngine::_global_ptr''()  + 0x54 bytes	C++
 	libpanda.dll!_CRT_INIT(void * hDllHandle=0x009e2b20, unsigned long dwReason=10363848, void * lpreserved=0x009e23c8)  Line 449	C
 	libpanda.dll!__DllMainCRTStartup(void * hDllHandle=0x01430000, unsigned long dwReason=0, void * lpreserved=0x00000000)  Line 560 + 0x8 bytes	C
 	libpanda.dll!_DllMainCRTStartup(void * hDllHandle=0x01430000, unsigned long dwReason=0, void * lpreserved=0x00000001)  Line 510 + 0xe bytes	C

Would appreciate any hints on where to start looking for the problem.

Let me see if I understand: you mean, by creating an offscreen buffer at runtime (which presumably works as far as it goes), you put Panda in a state in which it will crash on exit?

Perhaps something about the offscreen buffer has already been cleaned up by the time close_gsg() is called at exit, so the free_vbuffer() call is a kind of double-destruction.

David

You are understanding correctly. And double destruction is what came to mind, however I can’t think of what could be causing it.

If right after that call I do a remove_all_windows(), all windows are removed correctly and the app closes gracefully. It’s something that only happen on exit.

Perhaps there is some automatic DX cleanup that happens at exit, before the app gets the atexit() call.

David

Ok, something weird (or maybe it isn’t). I’m trying with 1.7.0 official build now; default configuration untouched except setting the gsg to DX.

This produces the crash on exit:

#include "pandaFramework.h"
#include "pandaSystem.h"

#pragma comment(linker, "/subsystem:console /ENTRY:mainCRTStartup")

PandaFramework framework;
 
int main(int argc, char *argv[]) {
    framework.open_framework(argc, argv);
    framework.set_window_title("My Panda3D Window");
    WindowFramework *window = framework.open_window();

    PT(GraphicsOutput) shadowBuffer = window->get_graphics_output()->make_texture_buffer("ShadowBuffer", 256, 256);

    NodePath environ = window->load_model(framework.get_models(),"environment");
    environ.reparent_to(window->get_render());

    framework.main_loop();
    framework.close_framework();
    return (0);
}

And if I remove the line “environ.reparent_to(window->get_render());”, it doesn’t crash.

But more importantly, the equivalent code in python doesn’t crash. Is this normal, or does it mean the problem is in Framework?

import direct.directbase.DirectStart
mybuffer = base.win.makeTextureBuffer("My Buffer", 256, 256)
environ = loader.loadModel("models/environment")
environ.reparentTo(render)
run()

I suspect the fundamental problem is that framework.close_framework() is not aggressively enough cleaning up the GSG’s. Maybe the cleanup code in Python’s ShowBase.destroy() is doing a better job of deleting stuff before exit.

The crash itself happens in the atexit() callback on the GSG, so something is remaining that thinks it still needs to be cleaned up, even though it has already already been so (perhaps outside of Panda).

David

Are you sure about that? Because I commented the atexit() call on the dxgsg9 (which is the only one being called for me, I think) so atexit_function() shouldn’t be being called anymore, and still get the crash, although I will double check. However, thanks for the pointers, I’ll compare the code of both.

Well, no, I’m not at all sure. Just throwing out guesses. :confused:

David

Ok, so I “fixed” the crash, although I don’t understand it.

I did two things, first thing comment the call to close_framework() inside the destructor of PandaFramework and avoid calling close_framework on my program.

Right after I did that, I started getting a much clearer breakpoint that lead me to this crash in the Release() call below (wdxGraphicsBuffer9.cxx):

  if (_depth_backing_store) {
    _depth_backing_store->Release();
    _depth_backing_store = NULL;
  }

So I commented the Release() call and it works perfectly now. I just didn’t find what could be causing _depth_backing_store to not be NULL, yet to be invalid at the same time. A race condition maybe?

Hmm, that does sound like trouble. Is anything else freeing that pointer, perhaps?

David

Well, just to be sure I set to NULL every released surface in the whole dxgsg9/ folder. Still nothing. This escapes my limited debugging skills, I’ll continue looking into it other day, at least I got rid of the crash for now, though I’m not releasing that buffer.