[glib/wip/th/fix-small-array-hash-valgrind: 3/3] ghash: clear hash table before invoking cleanup functions in g_hash_table_remove_all_nodes()
- From: Thomas Haller <thaller src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/wip/th/fix-small-array-hash-valgrind: 3/3] ghash: clear hash table before invoking cleanup functions in g_hash_table_remove_all_nodes()
- Date: Wed, 15 May 2019 14:56:08 +0000 (UTC)
commit 92f12d240d7e24605b14ef415d89eef61abddc2d
Author: Thomas Haller <thaller redhat com>
Date: Wed May 15 16:36:17 2019 +0200
ghash: clear hash table before invoking cleanup functions in g_hash_table_remove_all_nodes()
Invoking the cleanup function gives control back to the caller, who
might again call into the hash-table. Probably, doing that would be
error prone and a bad idea.
Anyway, we should not call into external code while the hash table is in
an inconsistent state. Reset the have_big_keys/have_big_values flags
first.
glib/ghash.c | 29 +++++++++++++++++------------
1 file changed, 17 insertions(+), 12 deletions(-)
---
diff --git a/glib/ghash.c b/glib/ghash.c
index 68dcb9bd4..bc232759a 100644
--- a/glib/ghash.c
+++ b/glib/ghash.c
@@ -581,6 +581,8 @@ g_hash_table_remove_all_nodes (GHashTable *hash_table,
gpointer *old_keys;
gpointer *old_values;
guint *old_hashes;
+ gboolean old_have_big_keys;
+ gboolean old_have_big_values;
/* If the hash table is already empty, there is nothing to be done. */
if (hash_table->nnodes == 0)
@@ -610,10 +612,12 @@ g_hash_table_remove_all_nodes (GHashTable *hash_table,
}
/* Keep the old storage space around to iterate over it. */
- old_size = hash_table->size;
- old_keys = hash_table->keys;
- old_values = hash_table->values;
- old_hashes = hash_table->hashes;
+ old_size = hash_table->size;
+ old_keys = hash_table->keys;
+ old_values = hash_table->values;
+ old_hashes = hash_table->hashes;
+ old_have_big_keys = hash_table->have_big_keys;
+ old_have_big_values = hash_table->have_big_values;
/* Now create a new storage space; If the table is destroyed we can use the
* shortcut of not creating a new storage. This saves the allocation at the
@@ -622,9 +626,13 @@ g_hash_table_remove_all_nodes (GHashTable *hash_table,
* is not allowed. If accesses are done, then either an assert or crash
* *will* happen. */
g_hash_table_set_shift (hash_table, HASH_TABLE_MIN_SHIFT);
+
+ hash_table->have_big_keys = !hash_table->use_small_arrays;
+ hash_table->have_big_values = !hash_table->use_small_arrays;
+
if (!destruction)
{
- hash_table->keys = g_hash_table_realloc_key_or_value_array (NULL, hash_table->size,
!hash_table->use_small_arrays);
+ hash_table->keys = g_hash_table_realloc_key_or_value_array (NULL, hash_table->size,
hash_table->have_big_keys);
hash_table->values = hash_table->keys;
hash_table->hashes = g_new0 (guint, hash_table->size);
}
@@ -639,13 +647,13 @@ g_hash_table_remove_all_nodes (GHashTable *hash_table,
{
if (HASH_IS_REAL (old_hashes[i]))
{
- key = g_hash_table_fetch_key_or_value (old_keys, i, hash_table->have_big_keys);
- value = g_hash_table_fetch_key_or_value (old_values, i, hash_table->have_big_values);
+ key = g_hash_table_fetch_key_or_value (old_keys, i, old_have_big_keys);
+ value = g_hash_table_fetch_key_or_value (old_values, i, old_have_big_values);
old_hashes[i] = UNUSED_HASH_VALUE;
- g_hash_table_assign_key_or_value (old_keys, i, hash_table->have_big_keys, NULL);
- g_hash_table_assign_key_or_value (old_values, i, hash_table->have_big_values, NULL);
+ g_hash_table_assign_key_or_value (old_keys, i, old_have_big_keys, NULL);
+ g_hash_table_assign_key_or_value (old_values, i, old_have_big_values, NULL);
if (hash_table->key_destroy_func != NULL)
hash_table->key_destroy_func (key);
@@ -655,9 +663,6 @@ g_hash_table_remove_all_nodes (GHashTable *hash_table,
}
}
- hash_table->have_big_keys = !hash_table->use_small_arrays;
- hash_table->have_big_values = !hash_table->use_small_arrays;
-
/* Destroy old storage space. */
if (old_keys != old_values)
g_free (old_values);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]