uridownloader: fix deadlock near EOS
authorThiago Santos <ts.santos@sisa.samsung.com>
Fri, 20 Dec 2013 22:42:52 +0000 (19:42 -0300)
committerThiago Santos <ts.santos@sisa.samsung.com>
Tue, 24 Dec 2013 20:07:52 +0000 (17:07 -0300)
A deadlock can happen when the source sends EOS when
being put to NULL as the object lock is being held by the
thread that sets the element to NULL and is needed by
the event handler.

gst-libs/gst/uridownloader/gsturidownloader.c

index 28e0aff79a2b4646731b7eaf6a43d4aed48c4ed0..d4c9fa775e334b678747328668a29350bd8e9bbd 100644 (file)
@@ -249,41 +249,6 @@ done:
   }
 }
 
-/* Must be called with mutex locked. */
-static void
-gst_uri_downloader_stop (GstUriDownloader * downloader)
-{
-  GstPad *pad;
-  GstElement *urisrc;
-
-  if (!downloader->priv->urisrc)
-    return;
-
-  GST_DEBUG_OBJECT (downloader, "Stopping source element %s",
-      GST_ELEMENT_NAME (downloader->priv->urisrc));
-
-  /* remove the bus' sync handler */
-  gst_bus_set_sync_handler (downloader->priv->bus, NULL, NULL, NULL);
-  /* unlink the source element from the internal pad */
-  pad = gst_pad_get_peer (downloader->priv->pad);
-  if (pad) {
-    gst_pad_unlink (pad, downloader->priv->pad);
-    gst_object_unref (pad);
-  }
-  urisrc = downloader->priv->urisrc;
-  downloader->priv->urisrc = NULL;
-
-  GST_DEBUG_OBJECT (downloader, "Stopping source element %s",
-      GST_ELEMENT_NAME (urisrc));
-
-  /* set the element state to NULL */
-  gst_bus_set_flushing (downloader->priv->bus, TRUE);
-  gst_element_set_state (urisrc, GST_STATE_NULL);
-  gst_element_get_state (urisrc, NULL, NULL, GST_CLOCK_TIME_NONE);
-  gst_element_set_bus (urisrc, NULL);
-  gst_object_unref (urisrc);
-}
-
 void
 gst_uri_downloader_reset (GstUriDownloader * downloader)
 {
@@ -464,8 +429,35 @@ gst_uri_downloader_fetch_uri_with_range (GstUriDownloader * downloader,
 
 quit:
   {
-    gst_uri_downloader_stop (downloader);
-    GST_OBJECT_UNLOCK (downloader);
+    if (downloader->priv->urisrc) {
+      GstPad *pad;
+      GstElement *urisrc;
+
+      GST_DEBUG_OBJECT (downloader, "Stopping source element %s",
+          GST_ELEMENT_NAME (downloader->priv->urisrc));
+
+      /* remove the bus' sync handler */
+      gst_bus_set_sync_handler (downloader->priv->bus, NULL, NULL, NULL);
+      /* unlink the source element from the internal pad */
+      pad = gst_pad_get_peer (downloader->priv->pad);
+      if (pad) {
+        gst_pad_unlink (pad, downloader->priv->pad);
+        gst_object_unref (pad);
+      }
+      urisrc = downloader->priv->urisrc;
+      downloader->priv->urisrc = NULL;
+      GST_OBJECT_UNLOCK (downloader);
+
+      GST_DEBUG_OBJECT (downloader, "Stopping source element %s",
+          GST_ELEMENT_NAME (urisrc));
+
+      /* set the element state to NULL */
+      gst_bus_set_flushing (downloader->priv->bus, TRUE);
+      gst_element_set_state (urisrc, GST_STATE_NULL);
+      gst_element_get_state (urisrc, NULL, NULL, GST_CLOCK_TIME_NONE);
+      gst_element_set_bus (urisrc, NULL);
+      gst_object_unref (urisrc);
+    }
     g_mutex_unlock (&downloader->priv->download_lock);
     return download;
   }