[Gnucash-changes] r13196 - gnucash/trunk - Better handling of event removal. This allows us to actually

Derek Atkins warlord at cvs.gnucash.org
Fri Feb 10 17:43:20 EST 2006


Author: warlord
Date: 2006-02-10 17:43:19 -0500 (Fri, 10 Feb 2006)
New Revision: 13196
Trac: http://svn.gnucash.org/trac/changeset/13196

Modified:
   gnucash/trunk/ChangeLog
   gnucash/trunk/lib/libqof/qof/gnc-event.c
Log:
Better handling of event removal.  This allows us to actually
clean up, but also makes sure we don't destroy the handler
list out from under us as we're processing events.



Modified: gnucash/trunk/ChangeLog
===================================================================
--- gnucash/trunk/ChangeLog	2006-02-10 15:32:39 UTC (rev 13195)
+++ gnucash/trunk/ChangeLog	2006-02-10 22:43:19 UTC (rev 13196)
@@ -11,6 +11,11 @@
 	  detects that we're running on a "broken" system like Ubuntu.
 	  This is in response to #330539.
 
+	* lib/libqof/qof/gnc-event.c:
+	  Better handling of event removal.  This allows us to actually
+	  clean up, but also makes sure we don't destroy the handler
+	  list out from under us as we're processing events.
+
 2006-02-09  David Hampton  <hampton at employees.org>
 
 	* src/bin/gnucash-bin.c: Pass argc by reference instead of value

Modified: gnucash/trunk/lib/libqof/qof/gnc-event.c
===================================================================
--- gnucash/trunk/lib/libqof/qof/gnc-event.c	2006-02-10 15:32:39 UTC (rev 13195)
+++ gnucash/trunk/lib/libqof/qof/gnc-event.c	2006-02-10 22:43:19 UTC (rev 13196)
@@ -38,6 +38,8 @@
 /* Static Variables ************************************************/
 static guint  suspend_counter = 0;
 static gint   next_handler_id = 1;
+static guint  handler_run_level = 0;
+static guint  pending_deletes = 0;
 static GList *handlers = NULL;
 
 /* This static indicates the debugging module that this .o belongs to.  */
@@ -113,14 +115,20 @@
        of a generated event, such as GNC_EVENT_DESTROY.  In that case,
        we're in the middle of walking the GList and it is wrong to
        modify the list. So, instead, we just NULL the handler. */ 
-    /* handlers = g_list_remove_link (handlers, node); */
 
-    LEAVE ("(handler_id=%d) handler=%p data=%p", handler_id, hi->handler, hi->user_data);
-    /* safety */
+    LEAVE ("(handler_id=%d) handler=%p data=%p", handler_id,
+	   hi->handler, hi->user_data);
+
+    /* safety -- clear the handler in case we're running events now */
     hi->handler = NULL;
 
-    /* g_list_free_1 (node);
-       g_free (hi); */
+    if (handler_run_level == 0) {
+      handlers = g_list_remove_link (handlers, node);
+      g_list_free_1 (node);
+      g_free (hi);
+    } else {
+      pending_deletes++;
+    }
 
     return;
   }
@@ -177,6 +185,7 @@
       return;
   }
 
+  handler_run_level++;
   for (node = handlers; node; node = next_node)
   {
     HandlerInfo *hi = node->data;
@@ -184,8 +193,30 @@
     next_node = node->next;
     PINFO ("id=%d hi=%p han=%p", hi->handler_id, hi, hi->handler);
     if (hi->handler)
-      hi->handler ((GUID *)&entity->guid, entity->e_type, event_type, hi->user_data);
+      hi->handler ((GUID *)&entity->guid, entity->e_type,
+		   event_type, hi->user_data);
   }
+  handler_run_level--;
+
+  /* If we're the outtermost event runner and we have pending deletes
+   * then go delete the handlers now.
+   */
+  if (handler_run_level == 0 && pending_deletes)
+  {
+    for (node = handlers; node; node = next_node)
+    {
+      HandlerInfo *hi = node->data;
+      next_node = node->next;
+      if (hi->handler == NULL)
+      {
+	/* remove this node from the list, then free this node */
+	handlers = g_list_remove_link (handlers, node);
+	g_list_free_1 (node);
+	g_free (hi);
+      }
+    }
+    pending_deletes = 0;
+  }
 }
 
 void



More information about the gnucash-changes mailing list