Commit a3c7406c authored by Allison Karlitskaya's avatar Allison Karlitskaya
Browse files

GVariantTypeInfo: fix thread safety bug

Issue caught by Michael Meeks.  This patch based on his.

GVariantTypeInfo was dropping the reference count on the TypeInfo
structure before removing it from the hash table.  This means that
another thread could come along and grab the value from the hash table
in the meantime.

Solve this by holding the lock on the table before dropping the

Also: move the hash table initialisation inside of the lock to remove
the standard double-initialisation race plus a more insidious issue
caused by the fact that we free the hash table once it becomes empty.
parent 43b6c2b8
...@@ -739,13 +739,13 @@ g_variant_type_info_get (const GVariantType *type) ...@@ -739,13 +739,13 @@ g_variant_type_info_get (const GVariantType *type)
GVariantTypeInfo *info; GVariantTypeInfo *info;
gchar *type_string; gchar *type_string;
if G_UNLIKELY (g_variant_type_info_table == NULL)
g_variant_type_info_table = g_hash_table_new (g_str_hash,
type_string = g_variant_type_dup_string (type); type_string = g_variant_type_dup_string (type);
g_static_rec_mutex_lock (&g_variant_type_info_lock); g_static_rec_mutex_lock (&g_variant_type_info_lock);
if (g_variant_type_info_table == NULL)
g_variant_type_info_table = g_hash_table_new (g_str_hash,
info = g_hash_table_lookup (g_variant_type_info_table, type_string); info = g_hash_table_lookup (g_variant_type_info_table, type_string);
if (info == NULL) if (info == NULL)
...@@ -833,9 +833,9 @@ g_variant_type_info_unref (GVariantTypeInfo *info) ...@@ -833,9 +833,9 @@ g_variant_type_info_unref (GVariantTypeInfo *info)
{ {
ContainerInfo *container = (ContainerInfo *) info; ContainerInfo *container = (ContainerInfo *) info;
g_static_rec_mutex_lock (&g_variant_type_info_lock);
if (g_atomic_int_dec_and_test (&container->ref_count)) if (g_atomic_int_dec_and_test (&container->ref_count))
{ {
g_static_rec_mutex_lock (&g_variant_type_info_lock);
g_hash_table_remove (g_variant_type_info_table, g_hash_table_remove (g_variant_type_info_table,
container->type_string); container->type_string);
if (g_hash_table_size (g_variant_type_info_table) == 0) if (g_hash_table_size (g_variant_type_info_table) == 0)
...@@ -856,6 +856,8 @@ g_variant_type_info_unref (GVariantTypeInfo *info) ...@@ -856,6 +856,8 @@ g_variant_type_info_unref (GVariantTypeInfo *info)
else else
g_assert_not_reached (); g_assert_not_reached ();
} }
g_static_rec_mutex_unlock (&g_variant_type_info_lock);
} }
} }
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