issue with gsg reference count?

For some time I’ve been experiencing a weird error poping up “after” the very last line of my panda c++ program has been completed and is exiting!

Although not really a problem since it happens when the app closes, I’d like however to fix this in order for my P3D application to exit in an orderly and civilized way…

Here is the sketch code:

int main(int argc, char *argv[]) { 
...
...
	// close the windows framework
	framework.close_all_windows(); 	// OK
	framework.close_framework(); 	// *** offending: this is where ***
	
	return (0); 
}

The error manifests itself as :

:display:gsg:glgsg(error):c:\users\...\panda\src\glstuff\glGraphicsBuffer_src.cxx, line 1020:GL error 1282

So looking at glGraphicsBuffer_src.cxx

void CLP(GraphicsBuffer)::close_buffer() {
  
	check_host_valid();
 
	report_my_gl_errors(); *** here ! 
  
              ** here giving a look at _gsg its value is == 0
  ...

I’m therefore led to think all this is somewhat related to reference counting.
Since I have one GraphicsStateGuardianBase pointer defined at the very beginning of my app as

PT(GraphicsStateGuardianBase) gsgL = ml_Buffer->get_gsg();

Here is what I try to add to make sure this guy is gone

int main(int argc, char *argv[]) { 
...
...
	// close the windows framework
	framework.close_all_windows(); 	// OK

/***** added code lines *****/
	std::cout<< "gsgL ref_count: "<< gsgL->get_ref_count()<< "\n"; // *reports 4 !
	if (gsgL->get_ref_count()) {
		gsgL->remove_gsg(gsgL);
	}

	std::cout<< "gsgL ref_count:"<< gsgL->get_ref_count()<< "\n"; // *reports 4 !
	framework.do_frame(current_thread);
	std::cout<< "gsgL ref_count:"<< gsgL->get_ref_count()<< "\n"; // * reports 2 !
/*****/
	framework.close_framework(); 
	
	return (0); 	// crashes here!!!!!!!!
}

So the net result is that the program crashes at a time it is supposed to be completed… :cry:

EDIT: it seems that in the second case, at the time the program executes return(0) some Panda destructors are being called behind the curtains. One of them tries to run :

 void CLP(GraphicsStateGuardian)::release_texture(TextureContext *tc) {
  report_my_gl_errors();
  CLP(TextureContext) *gtc =DCAST(CLP(TextureContext), tc);

with a texture context tc = NULL !!!

Here is the program stack at the time of the crash

libpandagl.dll!GLGraphicsStateGuardian::release_texture(TextureContext * tc=0x00e2a578)  Line 3403	C++
libpanda.dll!PreparedGraphicsObjects::begin_frame(GraphicsStateGuardianBase * gsg=0x00e039d8, Thread * current_thread=0x00e02018)  Line 1217	C++
libpanda.dll!GraphicsStateGuardian::close_gsg()  Line 2442	C++
libpanda.dll!GraphicsPipe::close_gsg(GraphicsStateGuardian * gsg=0x00e039d8)  Line 119	C++
libpanda.dll!GraphicsEngine::close_gsg(GraphicsPipe * pipe=0x0140436e, GraphicsStateGuardian * gsg=0x00e02940)  Line 112	C++
libpanda.dll!GraphicsEngine::WindowRenderer::do_close(GraphicsEngine * engine=0x00e02a98, Thread * current_thread=0x00e02018)  + 0x22e bytes	C++
libpanda.dll!GraphicsEngine::remove_all_windows()  Line 548	C++
libp3framework.dll!PandaFramework::close_framework()  Line 184	C++
libp3framework.dll!PandaFramework::~PandaFramework()  Line 71	C++
NED.exe!MicrophoneAudioCursorDS::cleanup()  + 0x96 bytes	C++
msvcr90.dll!doexit(int code=0, int quick=0, int retcaller=0)  Line 591	C
msvcr90.dll!exit(int code=0)  Line 412 + 0xc bytes	C

The unwinding of destructors at program exit can be quite complex, and because all of this is managed automatically by the C++ compiler, problems of this nature can be difficult to track down. I’ve seen this problem from time to time as well, but have been lazy and let it slide, because (as you point out) this is happening at exit time anyway.

But you’re right, this does need to be fixed–we ought to be able to exit cleanly and consistently. I’ll take a closer look soon.

David