diff options
author | Milan Crha <mcrha@redhat.com> | 2014-02-21 03:12:30 +0800 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2014-02-21 03:12:30 +0800 |
commit | 967d37373f5e59a46203cd84ee84650928771143 (patch) | |
tree | a9fd77c258601035f007a28e1d719dda08e4bdf5 /mail | |
parent | 197c8e1274f70c035614cbb54c7926901d1b1db5 (diff) | |
download | gsoc2013-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.c | 2 | ||||
-rw-r--r-- | mail/em-folder-tree-model.c | 30 | ||||
-rw-r--r-- | mail/em-folder-tree-model.h | 1 |
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); |