The deferred window destruction code was destroying the windows in reverse
authorChristopher John Purnell <cjp@lost.org.uk>
Thu, 11 Dec 2003 21:29:43 +0000 (21:29 +0000)
committerChristopher John Purnell <cjp@lost.org.uk>
Thu, 11 Dec 2003 21:29:43 +0000 (21:29 +0000)
order.  This cased a crash when the call to glutDestroyWindow() for a sub
windows was immediately followed by a call to glutDestroyWindow() for it's
parent. fgCloseWindows() would call fgDestroyWindow() for the parent first
fgDestroyWindws() would recurse over the children and then fgCloseWindows()
would call fgDestroyWindow() again for the child.

I've replaced the single linked list with one of our two way link list
structures.  I've also moved it into fgStructure because that seemed the
consistent thing to do.

I said the the deferred windows destruction causes more problems then it
solves.

git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@396 7f0cb862-5218-0410-a997-914c9d46530a

src/freeglut_internal.h
src/freeglut_structure.c

index 03296e0..7ffb4b6 100644 (file)
@@ -546,8 +546,8 @@ struct tagSFG_Window
 typedef struct tagSFG_WindowList SFG_WindowList ;
 struct tagSFG_WindowList
 {
+    SFG_Node node;
     SFG_Window *window ;
-    SFG_WindowList *next ;
 };
 
 /*
@@ -558,6 +558,7 @@ struct tagSFG_Structure
 {
     SFG_List        Windows;      /* The global windows list            */
     SFG_List        Menus;        /* The global menus list              */
+    SFG_List        WindowsToDestroy;
 
     SFG_Window*     Window;       /* The currently active win.          */
     SFG_Menu*       Menu;         /* Same, but menu...                  */
index 6aa02fd..2c5f1fe 100644 (file)
@@ -42,6 +42,7 @@
 
 SFG_Structure fgStructure = { { NULL, NULL },  /* The list of windows       */
                               { NULL, NULL },  /* The list of menus         */
+                              { NULL, NULL },  /* Windows to Destroy list   */
                               NULL,            /* The current window        */
                               NULL,            /* The current menu          */
                               NULL,            /* The menu OpenGL context   */
@@ -172,14 +173,6 @@ SFG_Menu* fgCreateMenu( FGCBMenu menuCallback )
 }
 
 /*
- * Linked list of windows to destroy ... this is so we don't destroy a
- * window from the middle of its callback.  Some C compilers take an
- * extremely dim view of this.
- */
-
-static SFG_WindowList* WindowsToDestroy = ( SFG_WindowList* )NULL;
-
-/*
  * Function to add a window to the linked list of windows to destroy.
  * Subwindows are automatically added because they hang from the window
  * structure.
@@ -189,8 +182,7 @@ void fgAddToWindowDestroyList( SFG_Window* window )
     SFG_WindowList *new_list_entry =
         ( SFG_WindowList* )malloc( sizeof(SFG_WindowList ) );
     new_list_entry->window = window;
-    new_list_entry->next = WindowsToDestroy;
-    WindowsToDestroy = new_list_entry;
+    fgListAppend( &fgStructure.WindowsToDestroy, &new_list_entry->node );
 
     /*
      * Check if the window is the current one...
@@ -218,22 +210,13 @@ void fgAddToWindowDestroyList( SFG_Window* window )
  */
 void fgCloseWindows( )
 {
-    SFG_WindowList *window_ptr = WindowsToDestroy;
-    WindowsToDestroy = ( SFG_WindowList* )NULL;
-    /* In case the destroy callbacks cause more windows to be closed */
+    SFG_WindowList *window_ptr;
 
-    while( window_ptr )
+    while( window_ptr = fgStructure.WindowsToDestroy.First )
     {
-        SFG_WindowList *next = window_ptr->next;
         fgDestroyWindow( window_ptr->window );
+        fgListRemove( &fgStructure.WindowsToDestroy, &window_ptr->node );
         free( window_ptr );
-        window_ptr = next;
-
-        if( !window_ptr )
-        {
-            window_ptr = WindowsToDestroy;
-            WindowsToDestroy = ( SFG_WindowList* )NULL;
-        }
     }
 }
 
@@ -404,6 +387,7 @@ void fgCreateStructure( void )
 
     fgListInit(&fgStructure.Windows);
     fgListInit(&fgStructure.Menus);
+    fgListInit(&fgStructure.WindowsToDestroy);
 }
 
 /*
@@ -419,6 +403,11 @@ void fgDestroyStructure( void )
     freeglut_assert_ready;
 
     /*
+     * Clean up the WindowsToDestroy list.
+     */
+    fgCloseWindows();
+
+    /*
      * Make sure all windows and menus have been deallocated
      */
     while( menu = ( SFG_Menu * )fgStructure.Menus.First )