baseparse: don't deadlock when setting external index
authorTim-Philipp Müller <tim.muller@collabora.co.uk>
Tue, 19 Apr 2011 12:05:53 +0000 (13:05 +0100)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Tue, 19 Apr 2011 12:05:53 +0000 (13:05 +0100)
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

libs/gst/base/gstbaseparse.c

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