[gnome-menus] Memory leak fixes
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-menus] Memory leak fixes
- Date: Mon, 18 Nov 2013 23:20:29 +0000 (UTC)
commit fabf5ba19d1cead5c91c3669e48f090e7a60d16f
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Mon Nov 18 18:10:57 2013 -0500
Memory leak fixes
This time, with less crashes.
libmenu/entry-directories.c | 115 +++++++++++++++++++++++++++----------------
libmenu/gmenu-tree.c | 4 +-
2 files changed, 75 insertions(+), 44 deletions(-)
---
diff --git a/libmenu/entry-directories.c b/libmenu/entry-directories.c
index ee22a55..d602b99 100644
--- a/libmenu/entry-directories.c
+++ b/libmenu/entry-directories.c
@@ -64,7 +64,10 @@ struct CachedDir
guint have_read_entries : 1;
guint deleted : 1;
- guint references : 28;
+ guint references;
+
+ GFunc notify;
+ gpointer notify_data;
};
struct CachedDirMonitor
@@ -79,6 +82,12 @@ static void cached_dir_remove_reference (CachedDir *dir);
static void cached_dir_free (CachedDir *dir);
static gboolean cached_dir_load_entries_recursive (CachedDir *dir,
const char *dirname);
+static void cached_dir_unref (CachedDir *dir);
+static CachedDir * cached_dir_add_subdir (CachedDir *dir,
+ const char *basename,
+ const char *path);
+static gboolean cached_dir_remove_subdir (CachedDir *dir,
+ const char *basename);
static void handle_cached_dir_changed (MenuMonitor *monitor,
MenuMonitorEvent event,
@@ -91,18 +100,39 @@ static void handle_cached_dir_changed (MenuMonitor *monitor,
static CachedDir *dir_cache = NULL;
+static void
+clear_cache (CachedDir *dir,
+ gpointer *cache)
+{
+ *cache = NULL;
+}
+
static CachedDir *
cached_dir_new (const char *name)
{
CachedDir *dir;
dir = g_new0 (CachedDir, 1);
-
dir->name = g_strdup (name);
return dir;
}
+static CachedDir *
+cached_dir_new_full (const char *name,
+ GFunc notify,
+ gpointer notify_data)
+{
+ CachedDir *dir;
+
+ dir = cached_dir_new (name);
+
+ dir->notify = notify;
+ dir->notify_data = notify_data;
+
+ return dir;
+}
+
static void
cached_dir_free (CachedDir *dir)
{
@@ -126,7 +156,7 @@ cached_dir_free (CachedDir *dir)
dir->entries = NULL;
g_slist_foreach (dir->subdirs,
- (GFunc) cached_dir_free,
+ (GFunc) cached_dir_unref,
NULL);
g_slist_free (dir->subdirs);
dir->subdirs = NULL;
@@ -135,6 +165,32 @@ cached_dir_free (CachedDir *dir)
g_free (dir);
}
+static CachedDir *
+cached_dir_ref (CachedDir *dir)
+{
+ dir->references++;
+ return dir;
+}
+
+static void
+cached_dir_unref (CachedDir *dir)
+{
+ if (--dir->references)
+ {
+ CachedDir *parent;
+
+ parent = dir->parent;
+
+ if (parent != NULL)
+ cached_dir_remove_subdir (parent, dir->name);
+
+ if (dir->notify)
+ dir->notify (dir, dir->notify_data);
+
+ cached_dir_free (dir);
+ }
+}
+
static inline CachedDir *
find_subdir (CachedDir *dir,
const char *subdir)
@@ -213,7 +269,9 @@ cached_dir_lookup (const char *canonical)
int i;
if (dir_cache == NULL)
- dir_cache = cached_dir_new ("/");
+ dir_cache = cached_dir_new_full ("/",
+ (GFunc) clear_cache,
+ &dir_cache);
dir = dir_cache;
g_assert (canonical != NULL && canonical[0] == G_DIR_SEPARATOR);
@@ -227,12 +285,7 @@ cached_dir_lookup (const char *canonical)
{
CachedDir *subdir;
- if ((subdir = find_subdir (dir, split[i])) == NULL)
- {
- subdir = cached_dir_new (split[i]);
- dir->subdirs = g_slist_prepend (dir->subdirs, subdir);
- subdir->parent = dir;
- }
+ subdir = cached_dir_add_subdir (dir, split[i], NULL);
dir = subdir;
@@ -310,7 +363,7 @@ cached_dir_remove_entry (CachedDir *dir,
return FALSE;
}
-static gboolean
+static CachedDir *
cached_dir_add_subdir (CachedDir *dir,
const char *basename,
const char *path)
@@ -322,23 +375,23 @@ cached_dir_add_subdir (CachedDir *dir,
if (subdir != NULL)
{
subdir->deleted = FALSE;
- return TRUE;
+ return subdir;
}
subdir = cached_dir_new (basename);
- if (!cached_dir_load_entries_recursive (subdir, path))
+ if (path != NULL && !cached_dir_load_entries_recursive (subdir, path))
{
cached_dir_free (subdir);
- return FALSE;
+ return NULL;
}
menu_verbose ("Caching dir \"%s\"\n", basename);
subdir->parent = dir;
- dir->subdirs = g_slist_prepend (dir->subdirs, subdir);
+ dir->subdirs = g_slist_prepend (dir->subdirs, cached_dir_ref (subdir));
- return TRUE;
+ return subdir;
}
static gboolean
@@ -355,7 +408,7 @@ cached_dir_remove_subdir (CachedDir *dir,
if (subdir->references == 0)
{
- cached_dir_free (subdir);
+ cached_dir_unref (subdir);
dir->subdirs = g_slist_remove (dir->subdirs, subdir);
}
@@ -496,7 +549,7 @@ handle_cached_dir_changed (MenuMonitor *monitor,
switch (event)
{
case MENU_MONITOR_EVENT_CREATED:
- handled = cached_dir_add_subdir (dir, basename, path);
+ handled = cached_dir_add_subdir (dir, basename, path) != NULL;
break;
case MENU_MONITOR_EVENT_CHANGED:
@@ -668,7 +721,7 @@ cached_dir_remove_monitor (CachedDir *dir,
static void
cached_dir_add_reference (CachedDir *dir)
{
- dir->references++;
+ cached_dir_ref (dir);
if (dir->parent != NULL)
{
@@ -683,29 +736,7 @@ cached_dir_remove_reference (CachedDir *dir)
parent = dir->parent;
- if (--dir->references == 0 && dir->deleted)
- {
- if (dir->parent != NULL)
- {
- GSList *tmp;
-
- tmp = parent->subdirs;
- while (tmp != NULL)
- {
- CachedDir *subdir = tmp->data;
-
- if (!strcmp (subdir->name, dir->name))
- {
- parent->subdirs = g_slist_delete_link (parent->subdirs, tmp);
- break;
- }
-
- tmp = tmp->next;
- }
- }
-
- cached_dir_free (dir);
- }
+ cached_dir_unref (dir);
if (parent != NULL)
{
diff --git a/libmenu/gmenu-tree.c b/libmenu/gmenu-tree.c
index 61ca041..9aa94c5 100644
--- a/libmenu/gmenu-tree.c
+++ b/libmenu/gmenu-tree.c
@@ -163,7 +163,7 @@ static void gmenu_tree_resolve_files (GMenuTree *tree,
MenuLayoutNode *layout);
static void gmenu_tree_force_recanonicalize (GMenuTree *tree);
static void gmenu_tree_invoke_monitors (GMenuTree *tree);
-
+
static void gmenu_tree_item_unref_and_unset_parent (gpointer itemp);
typedef enum
@@ -1485,7 +1485,7 @@ gmenu_tree_directory_finalize (GMenuTreeDirectory *directory)
NULL);
g_slist_free (directory->contents);
directory->contents = NULL;
-
+
g_slist_foreach (directory->default_layout_info,
(GFunc) menu_layout_node_unref,
NULL);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]