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.
This commit is contained in:
@ -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),
|
||||
|
||||
Reference in New Issue
Block a user