[0.11] gst-plugins-good: soup: fix start/stop race in souphttpclientsink

Sebastian Dröge slomo at kemper.freedesktop.org
Tue Jan 10 05:33:00 PST 2012


Module: gst-plugins-good
Branch: 0.11
Commit: 5bb4dcd89c73296062d9de49d1493fb3b5439154
URL:    http://cgit.freedesktop.org/gstreamer/gst-plugins-good/commit/?id=5bb4dcd89c73296062d9de49d1493fb3b5439154

Author: Tim-Philipp Müller <tim.muller at collabora.co.uk>
Date:   Sat Dec 10 14:48:57 2011 +0000

soup: fix start/stop race in souphttpclientsink

Fix crash or hang in generic/states unit test when doing stop()
right after start(). Create main loop in the start function already
and not just in the thread function, so that stop() always has a
valid main loop to quit on. Also, calling g_main_loop_quit() before
g_main_loop_run() won't work and result in the stop function waiting
for the thread to join forever. Therefore, wait for the thread to
be ready and get the main loop running in the start() function, to
be sure stop() always works.

---

 ext/soup/gstsouphttpclientsink.c |   32 +++++++++++++++++++++++++++++++-
 1 files changed, 31 insertions(+), 1 deletions(-)

diff --git a/ext/soup/gstsouphttpclientsink.c b/ext/soup/gstsouphttpclientsink.c
index 494dd8d..13cc805 100644
--- a/ext/soup/gstsouphttpclientsink.c
+++ b/ext/soup/gstsouphttpclientsink.c
@@ -450,6 +450,20 @@ gst_soup_http_client_sink_get_times (GstBaseSink * sink, GstBuffer * buffer,
 
 }
 
+static gboolean
+thread_ready_idle_cb (gpointer data)
+{
+  GstSoupHttpClientSink *souphttpsink = GST_SOUP_HTTP_CLIENT_SINK (data);
+
+  GST_LOG_OBJECT (souphttpsink, "thread ready");
+
+  g_mutex_lock (souphttpsink->mutex);
+  g_cond_signal (souphttpsink->cond);
+  g_mutex_unlock (souphttpsink->mutex);
+
+  return FALSE;                 /* only run once */
+}
+
 static gpointer
 thread_func (gpointer ptr)
 {
@@ -457,7 +471,6 @@ thread_func (gpointer ptr)
 
   GST_DEBUG ("thread start");
 
-  souphttpsink->loop = g_main_loop_new (souphttpsink->context, TRUE);
   g_main_loop_run (souphttpsink->loop);
 
   GST_DEBUG ("thread quit");
@@ -473,13 +486,30 @@ gst_soup_http_client_sink_start (GstBaseSink * sink)
   if (souphttpsink->prop_session) {
     souphttpsink->session = souphttpsink->prop_session;
   } else {
+    GSource *source;
     GError *error = NULL;
 
     souphttpsink->context = g_main_context_new ();
 
+    /* set up idle source to signal when the main loop is running and
+     * it's safe for ::stop() to call g_main_loop_quit() */
+    source = g_idle_source_new ();
+    g_source_set_callback (source, thread_ready_idle_cb, sink, NULL);
+    g_source_attach (source, souphttpsink->context);
+    g_source_unref (source);
+
+    souphttpsink->loop = g_main_loop_new (souphttpsink->context, TRUE);
+
+    g_mutex_lock (souphttpsink->mutex);
+
     souphttpsink->thread = g_thread_create (thread_func, souphttpsink,
         TRUE, &error);
 
+    GST_LOG_OBJECT (souphttpsink, "waiting for main loop thread to start up");
+    g_cond_wait (souphttpsink->cond, souphttpsink->mutex);
+    g_mutex_unlock (souphttpsink->mutex);
+    GST_LOG_OBJECT (souphttpsink, "main loop thread running");
+
     souphttpsink->session =
         soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
         souphttpsink->context, SOUP_SESSION_USER_AGENT,



More information about the gstreamer-commits mailing list