From bcfb7a6cdd2c3eb2d6f3e9de4ca1f95fc973db76 Mon Sep 17 00:00:00 2001 From: Kristian Rietveld Date: Mon, 3 Oct 2011 22:38:42 +0200 Subject: [PATCH] Bug 659022 - gtk_tree_model_filter_clear_cache_helper: assertion failed This bug is resolved by fixing two things in gtk_tree_model_filter_row_deleted(): (1) It is possible for an elt to have elt->visible_siter == NULL, when it is deleted. Only call g_sequence_remove() if this pointer is non-NULL. (2) For the case len (level->seq) > 1, free the elt->children level if non-NULL. Failing to do this means the level will stick around. If this child level was not referenced, it will still have a zero ref count on its parent which cannot be removed! For both bugs unit tests have been added in the preceding commit. --- gtk/gtktreemodelfilter.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/gtk/gtktreemodelfilter.c b/gtk/gtktreemodelfilter.c index e5e4955e38..daa490bdab 100644 --- a/gtk/gtktreemodelfilter.c +++ b/gtk/gtktreemodelfilter.c @@ -2614,20 +2614,21 @@ gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model, gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter, TRUE, FALSE); + if (elt->children) + /* If this last node has children, then the recursion in free_level + * will release this reference. + */ + while (elt->ref_count > 1) + gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter, + FALSE, FALSE); + else + while (elt->ref_count > 0) + gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter, + FALSE, FALSE); + + if (g_sequence_get_length (level->seq) == 1) { - if (elt->children) - /* If this last node has children, then the recursion in free_level - * will release this reference. - */ - while (elt->ref_count > 1) - gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter, - FALSE, FALSE); - else - while (elt->ref_count > 0) - gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter, - FALSE, FALSE); - /* kill level */ gtk_tree_model_filter_free_level (filter, level, FALSE, TRUE, FALSE); } @@ -2636,16 +2637,16 @@ gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model, GSequenceIter *tmp; gboolean is_first; - /* Release last references, if needed */ - while (elt->ref_count > 0) - gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter, - FALSE, FALSE); - lookup_elt_with_offset (level->seq, elt->offset, &siter); is_first = g_sequence_get_begin_iter (level->seq) == siter; + if (elt->children) + gtk_tree_model_filter_free_level (filter, elt->children, + FALSE, TRUE, FALSE); + /* remove the row */ - g_sequence_remove (elt->visible_siter); + if (elt->visible_siter) + g_sequence_remove (elt->visible_siter); tmp = g_sequence_iter_next (siter); g_sequence_remove (siter); g_sequence_foreach_range (tmp, g_sequence_get_end_iter (level->seq),