mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 08:17:01 +00:00
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.
This commit is contained in:
parent
a65091802f
commit
5bb4dcd89c
1 changed files with 31 additions and 1 deletions
|
@ -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
|
static gpointer
|
||||||
thread_func (gpointer ptr)
|
thread_func (gpointer ptr)
|
||||||
{
|
{
|
||||||
|
@ -457,7 +471,6 @@ thread_func (gpointer ptr)
|
||||||
|
|
||||||
GST_DEBUG ("thread start");
|
GST_DEBUG ("thread start");
|
||||||
|
|
||||||
souphttpsink->loop = g_main_loop_new (souphttpsink->context, TRUE);
|
|
||||||
g_main_loop_run (souphttpsink->loop);
|
g_main_loop_run (souphttpsink->loop);
|
||||||
|
|
||||||
GST_DEBUG ("thread quit");
|
GST_DEBUG ("thread quit");
|
||||||
|
@ -473,13 +486,30 @@ gst_soup_http_client_sink_start (GstBaseSink * sink)
|
||||||
if (souphttpsink->prop_session) {
|
if (souphttpsink->prop_session) {
|
||||||
souphttpsink->session = souphttpsink->prop_session;
|
souphttpsink->session = souphttpsink->prop_session;
|
||||||
} else {
|
} else {
|
||||||
|
GSource *source;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
souphttpsink->context = g_main_context_new ();
|
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,
|
souphttpsink->thread = g_thread_create (thread_func, souphttpsink,
|
||||||
TRUE, &error);
|
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 =
|
souphttpsink->session =
|
||||||
soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
|
soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
|
||||||
souphttpsink->context, SOUP_SESSION_USER_AGENT,
|
souphttpsink->context, SOUP_SESSION_USER_AGENT,
|
||||||
|
|
Loading…
Reference in a new issue