gnome-menus-2.10.1: patch to plug a memory leak



Attached is a patch I found in the latest Fedora SRPM,
 
	gnome-menus-2.10.1-3.src.rpm

Applying this patch improves the response time of the menus
considerably. See below:

[From the Changelog]

	2005-04-05  Mark McLoughlin  <mark skynet ie>

        Fix memory leaks on reload - bug #172472. Basically,
        because of a cyclic reference we were leaking the entire
        tree every time we reloaded.
 
        * libmenu/menu-tree.c:
        (menu_tree_directory_unref_and_unset_parent),
        (menu_tree_entry_unref_and_unset_parent): helper functions.
        (menu_tree_directory_unref): unset the parent reference
        on entries and subdirs before unreffing them.
        (menu_tree_entry_new): don't take a ref on the parent.
        (process_layout), (process_only_unallocated): unset the
        parent reference when deleting entries and subdirs.
 
        * libmenu/desktop-entries.c: (desktop_entry_reload): add debug.
 
        * libmenu/entry-directories.c: (cached_dir_update_entry): don't
        unref the entry if reloading fails - desktop_entry_reload ()
        does that.
 

-Joseph

-- 
joseph_sacco [at] comcast [dot] net
--- gnome-menus-2.10.1/ChangeLog.fix-parent-references	2005-03-23 07:13:08.000000000 -0500
+++ gnome-menus-2.10.1/ChangeLog	2005-04-06 02:47:06.000000000 -0400
@@ -0,0 +1,21 @@
+2005-04-05  Mark McLoughlin  <mark skynet ie>
+
+	Fix memory leaks on reload - bug #172472. Basically,
+	because of a cyclic reference we were leaking the entire
+	tree every time we reloaded.
+
+	* libmenu/menu-tree.c:
+	(menu_tree_directory_unref_and_unset_parent),
+	(menu_tree_entry_unref_and_unset_parent): helper functions.
+	(menu_tree_directory_unref): unset the parent reference
+	on entries and subdirs before unreffing them.
+	(menu_tree_entry_new): don't take a ref on the parent.
+	(process_layout), (process_only_unallocated): unset the
+	parent reference when deleting entries and subdirs.
+
+	* libmenu/desktop-entries.c: (desktop_entry_reload): add debug.
+
+	* libmenu/entry-directories.c: (cached_dir_update_entry): don't
+	unref the entry if reloading fails - desktop_entry_reload ()
+	does that.
+
--- gnome-menus-2.10.1/libmenu/desktop-entries.c.fix-parent-references	2005-03-08 12:59:26.000000000 -0500
+++ gnome-menus-2.10.1/libmenu/desktop-entries.c	2005-04-06 02:47:06.000000000 -0400
@@ -339,6 +339,8 @@
 {
   g_return_val_if_fail (entry != NULL, NULL);
 
+  menu_verbose ("Re-loading desktop entry \"%s\"\n", entry->path);
+
   g_free (entry->categories);
   entry->categories = NULL;
 
--- gnome-menus-2.10.1/libmenu/entry-directories.c.fix-parent-references	2005-03-16 02:26:26.000000000 -0500
+++ gnome-menus-2.10.1/libmenu/entry-directories.c	2005-04-06 02:47:07.000000000 -0400
@@ -347,7 +347,6 @@
         {
           if (!desktop_entry_reload (tmp->data))
 	    {
-	      desktop_entry_unref (tmp->data);
 	      dir->entries = g_slist_delete_link (dir->entries, tmp);
 	    }
 
--- gnome-menus-2.10.1/libmenu/menu-tree.c.fix-parent-references	2005-03-22 05:34:24.000000000 -0500
+++ gnome-menus-2.10.1/libmenu/menu-tree.c	2005-04-06 02:47:07.000000000 -0400
@@ -102,6 +102,9 @@
 						 MenuLayoutNode *layout);
 static void      menu_tree_force_recanonicalize (MenuTree       *tree);
 static void      menu_tree_invoke_monitors      (MenuTree       *tree);
+
+static void menu_tree_entry_unref_and_unset_parent     (MenuTreeEntry     *entry);
+static void menu_tree_directory_unref_and_unset_parent (MenuTreeDirectory *directory);
      
 /*
  * The idea is that we cache the menu tree for either a given
@@ -963,13 +966,13 @@
   if (--directory->refcount == 0)
     {
       g_slist_foreach (directory->subdirs,
-                       (GFunc) menu_tree_directory_unref,
+                       (GFunc) menu_tree_directory_unref_and_unset_parent,
                        NULL);
       g_slist_free (directory->subdirs);
       directory->subdirs = NULL;
 
       g_slist_foreach (directory->entries,
-                       (GFunc) menu_tree_entry_unref,
+                       (GFunc) menu_tree_entry_unref_and_unset_parent,
                        NULL);
       g_slist_free (directory->entries);
       directory->entries = NULL;
@@ -987,6 +990,16 @@
     }
 }
 
+static void
+menu_tree_directory_unref_and_unset_parent (MenuTreeDirectory *directory)
+{
+  g_return_if_fail (directory != NULL);
+
+  directory->parent = NULL;
+
+  menu_tree_directory_unref (directory);
+}
+
 static int
 menu_tree_directory_compare (MenuTreeDirectory *a,
                              MenuTreeDirectory *b)
@@ -1016,7 +1029,7 @@
 
   retval = g_new0 (MenuTreeEntry, 1);
 
-  retval->parent          = menu_tree_directory_ref (parent);
+  retval->parent          = parent;
   retval->desktop_entry   = desktop_entry_ref (desktop_entry);
   retval->desktop_file_id = g_strdup (desktop_file_id);
   retval->refcount        = 1;
@@ -1058,6 +1071,16 @@
     }
 }
 
+static void
+menu_tree_entry_unref_and_unset_parent (MenuTreeEntry *entry)
+{
+  g_return_if_fail (entry != NULL);
+
+  entry->parent = NULL;
+
+  menu_tree_entry_unref (entry);
+}
+
 static int
 menu_tree_entry_compare (MenuTreeEntry *a,
                          MenuTreeEntry *b)
@@ -2711,7 +2734,6 @@
       return NULL;
     }
 
-  directory->entries = NULL;
   desktop_entry_set_foreach (entries,
                              (DesktopEntrySetForeachFunc) entries_listify_foreach,
                              directory);
@@ -2756,7 +2778,7 @@
         {
           directory->entries = g_slist_delete_link (directory->entries,
                                                    tmp);
-          menu_tree_entry_unref (entry);
+          menu_tree_entry_unref_and_unset_parent (entry);
         }
 
       tmp = next;
@@ -2789,7 +2811,7 @@
             {
               directory->entries = g_slist_delete_link (directory->entries,
                                                         tmp);
-              menu_tree_entry_unref (entry);
+              menu_tree_entry_unref_and_unset_parent (entry);
             }
 
           tmp = next;
@@ -2811,7 +2833,7 @@
         {
           directory->subdirs = g_slist_delete_link (directory->subdirs,
                                                     tmp);
-          menu_tree_directory_unref (subdir);
+          menu_tree_directory_unref_and_unset_parent (subdir);
         }
 
       tmp = next;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]