mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-04 10:16:17 +01:00
fixed race condition where references to partially initialized classes
2008-06-10 13:15:29 Tim Janik <timj@imendio.com> * gtype.c (g_type_class_ref): fixed race condition where references to partially initialized classes could be handed out. svn path=/trunk/; revision=6982
This commit is contained in:
parent
b15a223a8a
commit
e9f756f17e
@ -1,3 +1,8 @@
|
||||
2008-06-10 13:15:29 Tim Janik <timj@imendio.com>
|
||||
|
||||
* gtype.c (g_type_class_ref): fixed race condition where references to
|
||||
partially initialized classes could be handed out.
|
||||
|
||||
2008-05-28 Michael Natterer <mitch@imendio.com>
|
||||
|
||||
* Makefile.am: don't define G_DISABLE_SINGLE_INCLUDES, it's in
|
||||
|
@ -2363,20 +2363,19 @@ gpointer
|
||||
g_type_class_ref (GType type)
|
||||
{
|
||||
TypeNode *node;
|
||||
|
||||
/* optimize for common code path
|
||||
*/
|
||||
GType ptype;
|
||||
|
||||
/* optimize for common code path */
|
||||
G_WRITE_LOCK (&type_rw_lock);
|
||||
node = lookup_type_node_I (type);
|
||||
if (node && node->is_classed && node->data &&
|
||||
node->data->class.class && node->data->common.ref_count > 0)
|
||||
node->data->class.class &&
|
||||
node->data->class.init_state == INITIALIZED)
|
||||
{
|
||||
type_data_ref_Wm (node);
|
||||
G_WRITE_UNLOCK (&type_rw_lock);
|
||||
|
||||
return node->data->class.class;
|
||||
}
|
||||
|
||||
if (!node || !node->is_classed ||
|
||||
(node->data && node->data->common.ref_count < 1))
|
||||
{
|
||||
@ -2385,33 +2384,27 @@ g_type_class_ref (GType type)
|
||||
type_descriptive_name_I (type));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
type_data_ref_Wm (node);
|
||||
ptype = NODE_PARENT_TYPE (node);
|
||||
G_WRITE_UNLOCK (&type_rw_lock);
|
||||
|
||||
g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
|
||||
/* here, we either have node->data->class.class == NULL, or
|
||||
* node->data->class.init_state == INITIALIZED, because any
|
||||
* concurrently running initialization was guarded by class_init_rec_mutex.
|
||||
*/
|
||||
if (!node->data->class.class) /* class uninitialized */
|
||||
{
|
||||
GType ptype = NODE_PARENT_TYPE (node);
|
||||
GTypeClass *pclass = NULL;
|
||||
/* acquire reference on parent class */
|
||||
GTypeClass *pclass = ptype ? g_type_class_ref (ptype) : NULL;
|
||||
G_WRITE_LOCK (&type_rw_lock);
|
||||
if (node->data->class.class) /* class was initialized during parent class initialization? */
|
||||
INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
|
||||
type_class_init_Wm (node, pclass);
|
||||
G_WRITE_UNLOCK (&type_rw_lock);
|
||||
g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
|
||||
if (ptype)
|
||||
{
|
||||
pclass = g_type_class_ref (ptype);
|
||||
G_WRITE_LOCK (&type_rw_lock);
|
||||
node = lookup_type_node_I (type);
|
||||
if (node->data->class.class)
|
||||
INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
|
||||
}
|
||||
else
|
||||
{
|
||||
G_WRITE_LOCK (&type_rw_lock);
|
||||
node = lookup_type_node_I (type);
|
||||
}
|
||||
if (!node->data->class.class) /* class could have been initialized meanwhile */
|
||||
type_class_init_Wm (node, pclass);
|
||||
G_WRITE_UNLOCK (&type_rw_lock);
|
||||
g_static_rec_mutex_unlock (&class_init_rec_mutex);
|
||||
}
|
||||
g_static_rec_mutex_unlock (&class_init_rec_mutex);
|
||||
|
||||
return node->data->class.class;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user