diff options
author | Thiago Santos <thiago.sousa.santos@collabora.com> | 2013-07-02 23:16:59 -0300 |
---|---|---|
committer | Thiago Santos <thiago.sousa.santos@collabora.com> | 2013-07-03 10:23:45 -0300 |
commit | cd26bd51a193e27ba31563a7637ee1935787f74b (patch) | |
tree | bc8f31906159e99e98afdd82ab9431074f21db69 /gst-libs | |
parent | 0a88daaf8e51fb3f6eafc0cb33a628f58ab65805 (diff) | |
download | gstreamer-plugins-bad-cd26bd51a193e27ba31563a7637ee1935787f74b.tar.gz |
uridownloader: Simplify locking to fix deadlocks
Use object lock to protect variables from concurrent access and
use download_lock to only allow one download running
Diffstat (limited to 'gst-libs')
-rw-r--r-- | gst-libs/gst/uridownloader/gsturidownloader.c | 50 |
1 files changed, 26 insertions, 24 deletions
diff --git a/gst-libs/gst/uridownloader/gsturidownloader.c b/gst-libs/gst/uridownloader/gsturidownloader.c index 6056ac88a..696320289 100644 --- a/gst-libs/gst/uridownloader/gsturidownloader.c +++ b/gst-libs/gst/uridownloader/gsturidownloader.c @@ -39,7 +39,8 @@ struct _GstUriDownloaderPrivate GstPad *pad; GTimeVal *timeout; GstFragment *download; - GMutex lock; + GMutex download_lock; /* used to restrict to one download only */ + GCond cond; gboolean cancelled; }; @@ -99,7 +100,7 @@ gst_uri_downloader_init (GstUriDownloader * downloader) /* Create a bus to handle error and warning message from the source element */ downloader->priv->bus = gst_bus_new (); - g_mutex_init (&downloader->priv->lock); + g_mutex_init (&downloader->priv->download_lock); g_cond_init (&downloader->priv->cond); } @@ -136,7 +137,7 @@ gst_uri_downloader_finalize (GObject * object) { GstUriDownloader *downloader = GST_URI_DOWNLOADER (object); - g_mutex_clear (&downloader->priv->lock); + g_mutex_clear (&downloader->priv->download_lock); g_cond_clear (&downloader->priv->cond); G_OBJECT_CLASS (gst_uri_downloader_parent_class)->finalize (object); @@ -166,14 +167,10 @@ gst_uri_downloader_sink_event (GstPad * pad, GstObject * parent, downloader->priv->download->completed = TRUE; downloader->priv->download->download_stop_time = gst_util_get_timestamp (); - GST_OBJECT_UNLOCK (downloader); GST_DEBUG_OBJECT (downloader, "Signaling chain funtion"); - g_mutex_lock (&downloader->priv->lock); g_cond_signal (&downloader->priv->cond); - g_mutex_unlock (&downloader->priv->lock); - } else { - GST_OBJECT_UNLOCK (downloader); } + GST_OBJECT_UNLOCK (downloader); gst_event_unref (event); break; } @@ -267,21 +264,15 @@ gst_uri_downloader_stop (GstUriDownloader * downloader) urisrc = downloader->priv->urisrc; downloader->priv->urisrc = NULL; - /* unlock so it doesn't block on chain function while changing state */ - g_mutex_unlock (&downloader->priv->lock); - 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); - - /* caller expects the mutex to be locked */ - g_mutex_lock (&downloader->priv->lock); - gst_bus_set_flushing (downloader->priv->bus, TRUE); } void @@ -303,21 +294,18 @@ gst_uri_downloader_cancel (GstUriDownloader * downloader) g_object_unref (downloader->priv->download); downloader->priv->download = NULL; downloader->priv->cancelled = TRUE; - GST_OBJECT_UNLOCK (downloader); GST_DEBUG_OBJECT (downloader, "Signaling chain funtion"); - g_mutex_lock (&downloader->priv->lock); g_cond_signal (&downloader->priv->cond); - g_mutex_unlock (&downloader->priv->lock); } else { gboolean cancelled; cancelled = downloader->priv->cancelled; downloader->priv->cancelled = TRUE; - GST_OBJECT_UNLOCK (downloader); if (cancelled) GST_DEBUG_OBJECT (downloader, "Trying to cancell a download that was alredy cancelled"); } + GST_OBJECT_UNLOCK (downloader); } static gboolean @@ -390,8 +378,9 @@ gst_uri_downloader_fetch_uri_with_range (GstUriDownloader * downloader, GstStateChangeReturn ret; GstFragment *download = NULL; - g_mutex_lock (&downloader->priv->lock); + g_mutex_lock (&downloader->priv->download_lock); + GST_OBJECT_LOCK (downloader); if (downloader->priv->cancelled) { goto quit; } @@ -402,31 +391,45 @@ gst_uri_downloader_fetch_uri_with_range (GstUriDownloader * downloader, } gst_bus_set_flushing (downloader->priv->bus, FALSE); + GST_OBJECT_UNLOCK (downloader); ret = gst_element_set_state (downloader->priv->urisrc, GST_STATE_READY); + GST_OBJECT_LOCK (downloader); if (ret == GST_STATE_CHANGE_FAILURE) { goto quit; } + /* might have been cancelled because of failures in state change */ + if (downloader->priv->cancelled) { + goto quit; + } + if (!gst_uri_downloader_set_range (downloader, range_start, range_end)) { GST_WARNING_OBJECT (downloader, "Failed to set range"); goto quit; } downloader->priv->download = gst_fragment_new (); + GST_OBJECT_UNLOCK (downloader); ret = gst_element_set_state (downloader->priv->urisrc, GST_STATE_PLAYING); + GST_OBJECT_LOCK (downloader); if (ret == GST_STATE_CHANGE_FAILURE) { g_object_unref (downloader->priv->download); downloader->priv->download = NULL; goto quit; } + /* might have been cancelled because of failures in state change */ + if (downloader->priv->cancelled) { + goto quit; + } + /* wait until: * - the download succeed (EOS in the src pad) * - the download failed (Error message on the fetcher bus) * - the download was canceled */ GST_DEBUG_OBJECT (downloader, "Waiting to fetch the URI %s", uri); - g_cond_wait (&downloader->priv->cond, &downloader->priv->lock); + g_cond_wait (&downloader->priv->cond, GST_OBJECT_GET_LOCK (downloader)); if (downloader->priv->cancelled) { if (downloader->priv->download) { @@ -436,10 +439,8 @@ gst_uri_downloader_fetch_uri_with_range (GstUriDownloader * downloader, goto quit; } - GST_OBJECT_LOCK (downloader); download = downloader->priv->download; downloader->priv->download = NULL; - GST_OBJECT_UNLOCK (downloader); if (download != NULL) GST_INFO_OBJECT (downloader, "URI fetched successfully"); @@ -449,7 +450,8 @@ gst_uri_downloader_fetch_uri_with_range (GstUriDownloader * downloader, quit: { gst_uri_downloader_stop (downloader); - g_mutex_unlock (&downloader->priv->lock); + GST_OBJECT_UNLOCK (downloader); + g_mutex_unlock (&downloader->priv->download_lock); return download; } } |