baseparse: don't deadlock when setting external index

Protect index with its own lock. gst_index_get_writer_id() may take
the object lock internally (the default resolver, GST_INDEX_RESOLVER_PATH,
will anyway), so if we're using that to protect the index as well,
we'll deadlock.

https://bugzilla.gnome.org/show_bug.cgi?id=646811
This commit is contained in:
Tim-Philipp Müller 2011-04-19 13:05:53 +01:00
parent c364539620
commit b35d54dcd1

View file

@ -276,6 +276,8 @@ struct _GstBaseParsePrivate
GstIndex *index; GstIndex *index;
gint index_id; gint index_id;
gboolean own_index; gboolean own_index;
GStaticMutex index_lock;
/* seek table entries only maintained if upstream is BYTE seekable */ /* seek table entries only maintained if upstream is BYTE seekable */
gboolean upstream_seekable; gboolean upstream_seekable;
gboolean upstream_has_duration; gboolean upstream_has_duration;
@ -450,6 +452,8 @@ gst_base_parse_finalize (GObject * object)
parse->priv->index = NULL; parse->priv->index = NULL;
} }
g_static_mutex_free (&parse->priv->index_lock);
gst_base_parse_clear_queues (parse); gst_base_parse_clear_queues (parse);
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
@ -531,6 +535,8 @@ gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
parse->priv->pad_mode = GST_ACTIVATE_NONE; parse->priv->pad_mode = GST_ACTIVATE_NONE;
g_static_mutex_init (&parse->priv->index_lock);
/* init state */ /* init state */
gst_base_parse_reset (parse); gst_base_parse_reset (parse);
GST_DEBUG_OBJECT (parse, "init ok"); GST_DEBUG_OBJECT (parse, "init ok");
@ -1416,11 +1422,11 @@ gst_base_parse_add_index_entry (GstBaseParse * parse, guint64 offset,
associations[1].value = offset; associations[1].value = offset;
/* index might change on-the-fly, although that would be nutty app ... */ /* index might change on-the-fly, although that would be nutty app ... */
GST_OBJECT_LOCK (parse); g_static_mutex_lock (&parse->priv->index_lock);
gst_index_add_associationv (parse->priv->index, parse->priv->index_id, gst_index_add_associationv (parse->priv->index, parse->priv->index_id,
(key) ? GST_ASSOCIATION_FLAG_KEY_UNIT : GST_ASSOCIATION_FLAG_DELTA_UNIT, (key) ? GST_ASSOCIATION_FLAG_KEY_UNIT : GST_ASSOCIATION_FLAG_DELTA_UNIT,
2, (const GstIndexAssociation *) &associations); 2, (const GstIndexAssociation *) &associations);
GST_OBJECT_UNLOCK (parse); g_static_mutex_unlock (&parse->priv->index_lock);
if (key) { if (key) {
parse->priv->index_last_offset = offset; parse->priv->index_last_offset = offset;
@ -3384,7 +3390,7 @@ gst_base_parse_find_offset (GstBaseParse * parse, GstClockTime time,
goto exit; goto exit;
} }
GST_OBJECT_LOCK (parse); g_static_mutex_lock (&parse->priv->index_lock);
if (parse->priv->index) { if (parse->priv->index) {
/* Let's check if we have an index entry for that time */ /* Let's check if we have an index entry for that time */
entry = gst_index_get_assoc_entry (parse->priv->index, entry = gst_index_get_assoc_entry (parse->priv->index,
@ -3408,7 +3414,7 @@ gst_base_parse_find_offset (GstBaseParse * parse, GstClockTime time,
ts = GST_CLOCK_TIME_NONE; ts = GST_CLOCK_TIME_NONE;
} }
} }
GST_OBJECT_UNLOCK (parse); g_static_mutex_unlock (&parse->priv->index_lock);
exit: exit:
if (_ts) if (_ts)
@ -3736,17 +3742,18 @@ gst_base_parse_set_index (GstElement * element, GstIndex * index)
{ {
GstBaseParse *parse = GST_BASE_PARSE (element); GstBaseParse *parse = GST_BASE_PARSE (element);
GST_OBJECT_LOCK (parse); g_static_mutex_lock (&parse->priv->index_lock);
if (parse->priv->index) if (parse->priv->index)
gst_object_unref (parse->priv->index); gst_object_unref (parse->priv->index);
if (index) { if (index) {
parse->priv->index = gst_object_ref (index); parse->priv->index = gst_object_ref (index);
gst_index_get_writer_id (index, GST_OBJECT (element), gst_index_get_writer_id (index, GST_OBJECT_CAST (element),
&parse->priv->index_id); &parse->priv->index_id);
parse->priv->own_index = FALSE; parse->priv->own_index = FALSE;
} else } else {
parse->priv->index = NULL; parse->priv->index = NULL;
GST_OBJECT_UNLOCK (parse); }
g_static_mutex_unlock (&parse->priv->index_lock);
} }
static GstIndex * static GstIndex *
@ -3755,10 +3762,10 @@ gst_base_parse_get_index (GstElement * element)
GstBaseParse *parse = GST_BASE_PARSE (element); GstBaseParse *parse = GST_BASE_PARSE (element);
GstIndex *result = NULL; GstIndex *result = NULL;
GST_OBJECT_LOCK (parse); g_static_mutex_lock (&parse->priv->index_lock);
if (parse->priv->index) if (parse->priv->index)
result = gst_object_ref (parse->priv->index); result = gst_object_ref (parse->priv->index);
GST_OBJECT_UNLOCK (parse); g_static_mutex_unlock (&parse->priv->index_lock);
return result; return result;
} }
@ -3775,6 +3782,7 @@ gst_base_parse_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_READY_TO_PAUSED: case GST_STATE_CHANGE_READY_TO_PAUSED:
/* If this is our own index destroy it as the /* If this is our own index destroy it as the
* old entries might be wrong for the new stream */ * old entries might be wrong for the new stream */
g_static_mutex_lock (&parse->priv->index_lock);
if (parse->priv->own_index) { if (parse->priv->own_index) {
gst_object_unref (parse->priv->index); gst_object_unref (parse->priv->index);
parse->priv->index = NULL; parse->priv->index = NULL;
@ -3790,6 +3798,7 @@ gst_base_parse_change_state (GstElement * element, GstStateChange transition)
&parse->priv->index_id); &parse->priv->index_id);
parse->priv->own_index = TRUE; parse->priv->own_index = TRUE;
} }
g_static_mutex_unlock (&parse->priv->index_lock);
break; break;
default: default:
break; break;