From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:36713) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UXznj-0002lv-NS for qemu-devel@nongnu.org; Thu, 02 May 2013 16:08:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UXzni-0000r7-7T for qemu-devel@nongnu.org; Thu, 02 May 2013 16:08:23 -0400 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Thu, 2 May 2013 22:08:59 +0200 Message-Id: <1367525344-7755-3-git-send-email-hpoussin@reactos.org> In-Reply-To: <1367525344-7755-1-git-send-email-hpoussin@reactos.org> References: <1367525344-7755-1-git-send-email-hpoussin@reactos.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PATCH 2/7] qom: handle registration of new types when initializing the first ones List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Herv=C3=A9=20Poussineau?= , qemu-ppc@nongnu.org, =?UTF-8?q?Andreas=20F=C3=A4rber?= When initializing all types in object_class_foreach, called by object_cla= ss_get_list, some new types may be registered. Those will change the type internal has= htable which is currently enumerated, and may crash QEMU. Fix it, by adding a second hash table which contains all the non-initiali= zed types, merged to the main one before each round of initializations. Bug has been detected when registering dynamic types containing an interf= ace. Signed-off-by: Herv=C3=A9 Poussineau --- qom/object.c | 45 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/qom/object.c b/qom/object.c index 75e6aac..e0a24dc 100644 --- a/qom/object.c +++ b/qom/object.c @@ -65,25 +65,39 @@ struct TypeImpl =20 static Type type_interface; =20 +static GHashTable *type_table_to_initialize; +static GHashTable *type_table_initialized; + static GHashTable *type_table_get(void) { - static GHashTable *type_table; - - if (type_table =3D=3D NULL) { - type_table =3D g_hash_table_new(g_str_hash, g_str_equal); + if (!type_table_initialized) { + type_table_initialized =3D g_hash_table_new(g_str_hash, g_str_eq= ual); } =20 - return type_table; + return type_table_initialized; } =20 static void type_table_add(TypeImpl *ti) { - g_hash_table_insert(type_table_get(), (void *)ti->name, ti); + GHashTable **type_table; + if (ti->class) { + type_table =3D &type_table_initialized; + } else { + type_table =3D &type_table_to_initialize; + } + if (!*type_table) { + *type_table =3D g_hash_table_new(g_str_hash, g_str_equal); + } + g_hash_table_insert(*type_table, (void *)ti->name, ti); } =20 static TypeImpl *type_table_lookup(const char *name) { - return g_hash_table_lookup(type_table_get(), name); + TypeImpl *ret =3D g_hash_table_lookup(type_table_get(), name); + if (!ret && type_table_to_initialize) { + ret =3D g_hash_table_lookup(type_table_to_initialize, name); + } + return ret; } =20 static TypeImpl *type_register_internal(const TypeInfo *info) @@ -573,13 +587,28 @@ static void object_class_foreach_tramp(gpointer key= , gpointer value, data->fn(k, data->opaque); } =20 +static void object_class_merge(gpointer key, gpointer value, + gpointer opaque) +{ + g_hash_table_insert(type_table_get(), key, value); +} + void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque), const char *implements_type, bool include_abst= ract, void *opaque) { OCFData data =3D { fn, implements_type, include_abstract, opaque }; =20 - g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &= data); + while (type_table_to_initialize && + g_hash_table_size(type_table_to_initialize) > 0) { + g_hash_table_foreach(type_table_to_initialize, object_class_merg= e, + NULL); + g_hash_table_destroy(type_table_to_initialize); + type_table_to_initialize =3D NULL; + + g_hash_table_foreach(type_table_get(), object_class_foreach_tram= p, + &data); + } } =20 int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opa= que), --=20 1.7.10.4