From: Aleix Conchillo Flaque Date: Thu, 27 Sep 2012 19:17:58 +0000 (-0700) Subject: rtspsrc: do not change state to PLAYING if currently chaning state X-Git-Tag: 1.19.3~509^2~6327 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3503aef946649da39e9b423adebe173f7a692b89;p=platform%2Fupstream%2Fgstreamer.git rtspsrc: do not change state to PLAYING if currently chaning state * gst/rtsp/gstrtspsrc.c (gst_rtspsrc_play): state change might be happening in the application thread, so we don't change the state to PLAYING in the gstrtspsrc thread unless it is safe. A specific case is when chaning the state to NULL from the application thread. This will synchronously try to stop the task (with the element state lock acquired), but we will try a gst_element_set_state from gstrtspsrc thread which will block on the element state lock causing a deadlock. https://bugzilla.gnome.org/show_bug.cgi?id=684312 --- diff --git a/gst/rtsp/gstrtspsrc.c b/gst/rtsp/gstrtspsrc.c index 03398fc..f8fea02 100644 --- a/gst/rtsp/gstrtspsrc.c +++ b/gst/rtsp/gstrtspsrc.c @@ -6144,8 +6144,23 @@ gst_rtspsrc_play (GstRTSPSrc * src, GstSegment * segment, gboolean async) * only in async case, since receive elements may not have been affected * by overall state change (e.g. not around yet), * do not mess with state in sync case (e.g. seeking) */ - if (async) - gst_element_set_state (GST_ELEMENT_CAST (src), GST_STATE_PLAYING); + if (async) { + /* state change might be happening in the application thread. A + * specific case is when chaging state to NULL where we will wait + * for this task to finish (gst_rtspsrc_stop). However this task + * will try to change the state to PLAYING causing a deadlock. */ + + /* make sure we are not in the middle of a state change. The + * state lock is a recursive lock so it's safe to lock twice from + * the same thread */ + if (GST_STATE_TRYLOCK (src)) { + gst_element_set_state (GST_ELEMENT_CAST (src), GST_STATE_PLAYING); + GST_STATE_UNLOCK (src); + } else { + res = GST_RTSP_ERROR; + goto changing_state; + } + } /* construct a control url */ if (src->control) @@ -6308,6 +6323,11 @@ was_playing: GST_DEBUG_OBJECT (src, "we were already PLAYING"); goto done; } +changing_state: + { + GST_DEBUG_OBJECT (src, "failed going to PLAYING, already changing state"); + goto done; + } create_request_failed: { gchar *str = gst_rtsp_strresult (res);