aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2014-02-21 03:12:30 +0800
committerMilan Crha <mcrha@redhat.com>2014-02-21 03:12:30 +0800
commit967d37373f5e59a46203cd84ee84650928771143 (patch)
treea9fd77c258601035f007a28e1d719dda08e4bdf5 /mail
parent197c8e1274f70c035614cbb54c7926901d1b1db5 (diff)
downloadgsoc2013-evolution-967d37373f5e59a46203cd84ee84650928771143.tar.gz
gsoc2013-evolution-967d37373f5e59a46203cd84ee84650928771143.tar.zst
gsoc2013-evolution-967d37373f5e59a46203cd84ee84650928771143.zip
EMFolderTreeModel: Fix a circular dependency between model and its data
The model stores GtkTreeRowReference-s in its private data, but these references ref the model, thus there is a circular dependency between internal data and the object itself, effectively causing memory leaks. With this fixed, the CamelSession is correctly freed at the end of the application.
Diffstat (limited to 'mail')
-rw-r--r--mail/e-mail-backend.c2
-rw-r--r--mail/em-folder-tree-model.c30
-rw-r--r--mail/em-folder-tree-model.h1
3 files changed, 29 insertions, 4 deletions
diff --git a/mail/e-mail-backend.c b/mail/e-mail-backend.c
index 83ee93d45e..8e45ae101f 100644
--- a/mail/e-mail-backend.c
+++ b/mail/e-mail-backend.c
@@ -923,6 +923,8 @@ mail_backend_dispose (GObject *object)
priv = E_MAIL_BACKEND_GET_PRIVATE (object);
if (priv->session != NULL) {
+ em_folder_tree_model_free_default ();
+
g_signal_handlers_disconnect_matched (
priv->session, G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL, object);
diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c
index 789bb20e38..3597b6ec6c 100644
--- a/mail/em-folder-tree-model.c
+++ b/mail/em-folder-tree-model.c
@@ -844,17 +844,39 @@ em_folder_tree_model_new (void)
return g_object_new (EM_TYPE_FOLDER_TREE_MODEL, NULL);
}
-EMFolderTreeModel *
-em_folder_tree_model_get_default (void)
+static EMFolderTreeModel *
+em_folder_tree_manage_default (gboolean do_create)
{
- static EMFolderTreeModel *default_folder_tree_model;
+ static EMFolderTreeModel *default_folder_tree_model = NULL;
- if (G_UNLIKELY (default_folder_tree_model == NULL))
+ if (do_create && G_UNLIKELY (default_folder_tree_model == NULL)) {
default_folder_tree_model = em_folder_tree_model_new ();
+ } else if (!do_create && G_UNLIKELY (default_folder_tree_model != NULL)) {
+ /* This is necessary, due to circular dependency between stored GtkTreeRwoReference
+ and the model itself. */
+ g_mutex_lock (&default_folder_tree_model->priv->store_index_lock);
+ g_hash_table_remove_all (default_folder_tree_model->priv->store_index);
+ g_mutex_unlock (&default_folder_tree_model->priv->store_index_lock);
+
+ g_object_unref (default_folder_tree_model);
+ default_folder_tree_model = NULL;
+ }
return default_folder_tree_model;
}
+EMFolderTreeModel *
+em_folder_tree_model_get_default (void)
+{
+ return em_folder_tree_manage_default (TRUE);
+}
+
+void
+em_folder_tree_model_free_default (void)
+{
+ em_folder_tree_manage_default (FALSE);
+}
+
GtkTreeSelection *
em_folder_tree_model_get_selection (EMFolderTreeModel *model)
{
diff --git a/mail/em-folder-tree-model.h b/mail/em-folder-tree-model.h
index 3684082e98..60c884a872 100644
--- a/mail/em-folder-tree-model.h
+++ b/mail/em-folder-tree-model.h
@@ -101,6 +101,7 @@ EMFolderTreeModel *
em_folder_tree_model_new (void);
EMFolderTreeModel *
em_folder_tree_model_get_default (void);
+void em_folder_tree_model_free_default (void);
GtkTreeSelection *
em_folder_tree_model_get_selection
(EMFolderTreeModel *model);