Commit cc72d687 authored by Morten Welinder's avatar Morten Welinder Committed by Morten Welinder

Another case of don't-muck-with-the-hash-you-are-iterating-over.

2005-08-23  Morten Welinder  <terra@gnome.org>

	* src/dependent.c (dep_hash_destroy): Another case of
	don't-muck-with-the-hash-you-are-iterating-over.
parent 9409d3fe
2005-08-23 Morten Welinder <terra@gnome.org>
* src/dependent.c (dep_hash_destroy): Another case of
don't-muck-with-the-hash-you-are-iterating-over.
2005-08-18 Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr>
* src/commands.c (cmd_object_raise_redo): pull_to_front and
......
......@@ -8,6 +8,8 @@ Morten:
* Fix solver crash. [#314025]
* Fix solver coefficients.
* Package lp_solve into a single file and sanitize its API.
Update to lp_solve 5.5 in the process.
* Fix dependency crash. [Part of #314207]
--------------------------------------------------------------------------
Gnumeric 1.5.3
......
2005-08-23 Morten Welinder <terra@gnome.org>
* src/dependent.c (dep_hash_destroy): Another case of
don't-muck-with-the-hash-you-are-iterating-over.
2005-08-18 Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr>
* src/commands.c (cmd_object_raise_redo): pull_to_front and
......
......@@ -1692,90 +1692,80 @@ dependents_relocate (GnmExprRelocateInfo const *info)
/*******************************************************************/
struct cb_dep_hash_destroy {
GnmExprRewriteInfo rwinfo;
GSList *dyn_deps;
gboolean destroy;
Sheet *sheet;
};
/*
* WARNING : Hash is pointing to freed memory once this is complete
* This is tightly coupled with do_deps_destroy.
*/
static gboolean
cb_dep_hash_destroy (G_GNUC_UNUSED gpointer key,
DependencyAny *depany,
struct cb_dep_hash_destroy *closure)
{
GSList *deplist = NULL, *l;
micro_hash_foreach_dep (depany->deps, dep, {
if (dependent_type (dep) == DEPENDENT_DYNAMIC_DEP) {
GnmDependent *c = ((DynamicDep *)dep)->container;
if (!c->sheet->being_invalidated)
closure->dyn_deps =
g_slist_prepend (closure->dyn_deps, c);
} else if (!dep->sheet->being_invalidated) {
/*
* We collect here instead of doing right away as
* the dependent_set_expr below can change the
* container we are looping over.
*/
deplist = g_slist_prepend (deplist, dep);
}
});
for (l = deplist; l; l = l->next) {
GnmDependent *dep = l->data;
GnmExpr *e = (GnmExpr *)dep->expression;
/* We are told this dependent depends on this region, hence if
* newtree is null then either
* 1) we did not depend on it (ie., serious breakage )
* 2) we had a duplicate reference and we have already removed it.
* 3) We depended on things via a name which will be
* invalidated elsewhere */
GnmExpr const *newtree = gnm_expr_rewrite (e, &closure->rwinfo);
if (newtree != NULL) {
if (!closure->destroy) {
gnm_expr_ref (e);
closure->sheet->revive.dep_exprs =
g_slist_prepend
(g_slist_prepend (closure->sheet->revive.dep_exprs, e),
dep);
}
dependent_set_expr (dep, newtree);
gnm_expr_unref (newtree);
}
}
g_slist_free (deplist);
if (closure->destroy)
micro_hash_release (&depany->deps);
cb_collect_range (G_GNUC_UNUSED gpointer key,
DependencyAny *depany,
GSList **collector)
{
*collector = g_slist_prepend (*collector, depany);
return TRUE;
}
static void
dep_hash_destroy (GHashTable *hash, GSList **dyn_deps, Sheet *sheet, gboolean destroy)
{
struct cb_dep_hash_destroy closure;
closure.rwinfo.type = GNM_EXPR_REWRITE_INVALIDATE_SHEETS;
closure.dyn_deps = *dyn_deps;
closure.destroy = destroy;
closure.sheet = sheet;
GSList *deps = NULL, *l2;
GnmExprRewriteInfo rwinfo;
/* We collect first because we will be changing the hash. */
if (destroy) {
g_hash_table_foreach_remove (hash,
(GHRFunc)cb_dep_hash_destroy,
&closure);
(GHRFunc)cb_collect_range,
&deps);
g_hash_table_destroy (hash);
} else {
g_hash_table_foreach (hash,
(GHFunc)cb_dep_hash_destroy,
&closure);
g_hash_table_foreach (hash, (GHFunc)cb_collect_range, &deps);
}
*dyn_deps = closure.dyn_deps;
rwinfo.type = GNM_EXPR_REWRITE_INVALIDATE_SHEETS;
for (l2 = deps; l2; l2 = l2->next) {
DependencyAny *depany = l2->data;
GSList *deplist = NULL, *l;
micro_hash_foreach_dep (depany->deps, dep, {
if (dependent_type (dep) == DEPENDENT_DYNAMIC_DEP) {
GnmDependent *c = ((DynamicDep *)dep)->container;
if (!c->sheet->being_invalidated)
*dyn_deps =
g_slist_prepend (*dyn_deps, c);
} else if (!dep->sheet->being_invalidated) {
/*
* We collect here instead of doing right away as
* the dependent_set_expr below can change the
* container we are looping over.
*/
deplist = g_slist_prepend (deplist, dep);
}
});
for (l = deplist; l; l = l->next) {
GnmDependent *dep = l->data;
GnmExpr *e = (GnmExpr *)dep->expression;
/* We are told this dependent depends on this region, hence if
* newtree is null then either
* 1) we did not depend on it (ie., serious breakage )
* 2) we had a duplicate reference and we have already removed it.
* 3) We depended on things via a name which will be
* invalidated elsewhere */
GnmExpr const *newtree = gnm_expr_rewrite (e, &rwinfo);
if (newtree != NULL) {
if (!destroy) {
gnm_expr_ref (e);
sheet->revive.dep_exprs =
g_slist_prepend
(g_slist_prepend (sheet->revive.dep_exprs, e),
dep);
}
dependent_set_expr (dep, newtree);
gnm_expr_unref (newtree);
}
}
g_slist_free (deplist);
if (destroy)
micro_hash_release (&depany->deps);
}
g_slist_free (deps);
}
static void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment