mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-03 15:06:34 +00:00
gst/rtsp/gstrtspsrc.*: Protect connection activity with a new lock, avoids deadlocks when going to PAUSED. Fixes #455...
Original commit message from CVS: * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_init), (gst_rtspsrc_finalize), (gst_rtspsrc_connection_send), (gst_rtspsrc_connection_receive), (gst_rtspsrc_sink_chain), (gst_rtspsrc_handle_request), (gst_rtspsrc_send_keep_alive), (gst_rtspsrc_loop_interleaved), (gst_rtspsrc_loop_udp), (gst_rtspsrc_try_send), (gst_rtspsrc_pause): * gst/rtsp/gstrtspsrc.h: Protect connection activity with a new lock, avoids deadlocks when going to PAUSED. Fixes #455808.
This commit is contained in:
parent
4d581cb606
commit
0dcafb0635
3 changed files with 84 additions and 27 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
2007-08-17 Wim Taymans <wim.taymans@gmail.com>
|
||||
|
||||
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_init),
|
||||
(gst_rtspsrc_finalize), (gst_rtspsrc_connection_send),
|
||||
(gst_rtspsrc_connection_receive), (gst_rtspsrc_sink_chain),
|
||||
(gst_rtspsrc_handle_request), (gst_rtspsrc_send_keep_alive),
|
||||
(gst_rtspsrc_loop_interleaved), (gst_rtspsrc_loop_udp),
|
||||
(gst_rtspsrc_try_send), (gst_rtspsrc_pause):
|
||||
* gst/rtsp/gstrtspsrc.h:
|
||||
Protect connection activity with a new lock, avoids deadlocks when going
|
||||
to PAUSED. Fixes #455808.
|
||||
|
||||
2007-08-17 Wim Taymans <wim.taymans@gmail.com>
|
||||
|
||||
* gst/debug/rndbuffersize.c: (gst_rnd_buffer_size_loop):
|
||||
|
|
|
@ -312,9 +312,6 @@ gst_rtspsrc_class_init (GstRTSPSrcClass * klass)
|
|||
static void
|
||||
gst_rtspsrc_init (GstRTSPSrc * src, GstRTSPSrcClass * g_class)
|
||||
{
|
||||
src->stream_rec_lock = g_new (GStaticRecMutex, 1);
|
||||
g_static_rec_mutex_init (src->stream_rec_lock);
|
||||
|
||||
src->location = g_strdup (DEFAULT_LOCATION);
|
||||
src->url = NULL;
|
||||
|
||||
|
@ -325,8 +322,19 @@ gst_rtspsrc_init (GstRTSPSrc * src, GstRTSPSrcClass * g_class)
|
|||
gst_rtsp_ext_list_connect (src->extensions, "send",
|
||||
(GCallback) gst_rtspsrc_send_cb, src);
|
||||
|
||||
/* protects the streaming thread in interleaved mode or the polling
|
||||
* thread in UDP mode. */
|
||||
src->stream_rec_lock = g_new (GStaticRecMutex, 1);
|
||||
g_static_rec_mutex_init (src->stream_rec_lock);
|
||||
|
||||
/* protects our state changes from multiple invocations */
|
||||
src->state_rec_lock = g_new (GStaticRecMutex, 1);
|
||||
g_static_rec_mutex_init (src->state_rec_lock);
|
||||
|
||||
/* protects access to the server connection */
|
||||
src->conn_rec_lock = g_new (GStaticRecMutex, 1);
|
||||
g_static_rec_mutex_init (src->conn_rec_lock);
|
||||
|
||||
src->state = GST_RTSP_STATE_INVALID;
|
||||
}
|
||||
|
||||
|
@ -338,14 +346,18 @@ gst_rtspsrc_finalize (GObject * object)
|
|||
rtspsrc = GST_RTSPSRC (object);
|
||||
|
||||
gst_rtsp_ext_list_free (rtspsrc->extensions);
|
||||
g_static_rec_mutex_free (rtspsrc->stream_rec_lock);
|
||||
g_free (rtspsrc->stream_rec_lock);
|
||||
g_free (rtspsrc->location);
|
||||
g_free (rtspsrc->req_location);
|
||||
g_free (rtspsrc->content_base);
|
||||
gst_rtsp_url_free (rtspsrc->url);
|
||||
|
||||
/* free locks */
|
||||
g_static_rec_mutex_free (rtspsrc->stream_rec_lock);
|
||||
g_free (rtspsrc->stream_rec_lock);
|
||||
g_static_rec_mutex_free (rtspsrc->state_rec_lock);
|
||||
g_free (rtspsrc->state_rec_lock);
|
||||
g_static_rec_mutex_free (rtspsrc->conn_rec_lock);
|
||||
g_free (rtspsrc->conn_rec_lock);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
@ -1091,6 +1103,32 @@ gst_rtspsrc_flush (GstRTSPSrc * src, gboolean flush)
|
|||
gst_rtspsrc_push_event (src, event);
|
||||
}
|
||||
|
||||
static GstRTSPResult
|
||||
gst_rtspsrc_connection_send (GstRTSPSrc * src, GstRTSPMessage * message,
|
||||
GTimeVal * timeout)
|
||||
{
|
||||
GstRTSPResult ret;
|
||||
|
||||
GST_RTSP_CONN_LOCK (src);
|
||||
ret = gst_rtsp_connection_send (src->connection, message, timeout);
|
||||
GST_RTSP_CONN_UNLOCK (src);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstRTSPResult
|
||||
gst_rtspsrc_connection_receive (GstRTSPSrc * src, GstRTSPMessage * message,
|
||||
GTimeVal * timeout)
|
||||
{
|
||||
GstRTSPResult ret;
|
||||
|
||||
GST_RTSP_CONN_LOCK (src);
|
||||
ret = gst_rtsp_connection_receive (src->connection, message, timeout);
|
||||
GST_RTSP_CONN_UNLOCK (src);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_rtspsrc_do_seek (GstRTSPSrc * src, GstSegment * segment)
|
||||
{
|
||||
|
@ -1353,7 +1391,7 @@ gst_rtspsrc_sink_chain (GstPad * pad, GstBuffer * buffer)
|
|||
gst_rtsp_message_take_body (&message, data, size);
|
||||
|
||||
GST_DEBUG_OBJECT (src, "sending %u bytes RTCP", size);
|
||||
ret = gst_rtsp_connection_send (src->connection, &message, NULL);
|
||||
ret = gst_rtspsrc_connection_send (src, &message, NULL);
|
||||
GST_DEBUG_OBJECT (src, "sent RTCP, %d", ret);
|
||||
|
||||
/* and steal it away again because we will free it when unreffing the
|
||||
|
@ -2218,7 +2256,8 @@ gst_rtspsrc_handle_request (GstRTSPSrc * src, GstRTSPMessage * request)
|
|||
if (src->debug)
|
||||
gst_rtsp_message_dump (&response);
|
||||
|
||||
if ((res = gst_rtsp_connection_send (src->connection, &response, NULL)) < 0)
|
||||
res = gst_rtspsrc_connection_send (src, &response, NULL);
|
||||
if (res < 0)
|
||||
goto send_error;
|
||||
|
||||
return GST_RTSP_OK;
|
||||
|
@ -2253,7 +2292,8 @@ gst_rtspsrc_send_keep_alive (GstRTSPSrc * src)
|
|||
if (src->debug)
|
||||
gst_rtsp_message_dump (&request);
|
||||
|
||||
if ((res = gst_rtsp_connection_send (src->connection, &request, NULL)) < 0)
|
||||
res = gst_rtspsrc_connection_send (src, &request, NULL);
|
||||
if (res < 0)
|
||||
goto send_error;
|
||||
|
||||
gst_rtsp_connection_reset_timeout (src->connection);
|
||||
|
@ -2305,9 +2345,9 @@ gst_rtspsrc_loop_interleaved (GstRTSPSrc * src)
|
|||
|
||||
GST_DEBUG_OBJECT (src, "doing receive");
|
||||
|
||||
res =
|
||||
gst_rtsp_connection_receive (src->connection, &message,
|
||||
src->ptcp_timeout);
|
||||
/* protect the connection with the connection lock so that we can see when
|
||||
* we are finished doing server communication */
|
||||
res = gst_rtspsrc_connection_receive (src, &message, src->ptcp_timeout);
|
||||
|
||||
switch (res) {
|
||||
case GST_RTSP_OK:
|
||||
|
@ -2544,8 +2584,7 @@ gst_rtspsrc_loop_udp (GstRTSPSrc * src)
|
|||
/* we should continue reading the TCP socket because the server might
|
||||
* send us requests. When the session timeout expires, we need to send a
|
||||
* keep-alive request to keep the session open. */
|
||||
res =
|
||||
gst_rtsp_connection_receive (src->connection, &message, &tv_timeout);
|
||||
res = gst_rtspsrc_connection_receive (src, &message, &tv_timeout);
|
||||
|
||||
switch (res) {
|
||||
case GST_RTSP_OK:
|
||||
|
@ -2923,17 +2962,15 @@ again:
|
|||
if (src->debug)
|
||||
gst_rtsp_message_dump (request);
|
||||
|
||||
if ((res =
|
||||
gst_rtsp_connection_send (src->connection, request,
|
||||
src->ptcp_timeout)) < 0)
|
||||
res = gst_rtspsrc_connection_send (src, request, src->ptcp_timeout);
|
||||
if (res < 0)
|
||||
goto send_error;
|
||||
|
||||
gst_rtsp_connection_reset_timeout (src->connection);
|
||||
|
||||
next:
|
||||
if ((res =
|
||||
gst_rtsp_connection_receive (src->connection, response,
|
||||
src->ptcp_timeout)) < 0)
|
||||
res = gst_rtspsrc_connection_receive (src, response, src->ptcp_timeout);
|
||||
if (res < 0)
|
||||
goto receive_error;
|
||||
|
||||
if (src->debug)
|
||||
|
@ -4099,11 +4136,12 @@ gst_rtspsrc_pause (GstRTSPSrc * src)
|
|||
if (src->state == GST_RTSP_STATE_READY)
|
||||
goto was_paused;
|
||||
|
||||
/* wait for streaming to finish */
|
||||
GST_DEBUG_OBJECT (src, "waiting for streaming to finish");
|
||||
GST_RTSP_STREAM_LOCK (src);
|
||||
GST_DEBUG_OBJECT (src, "streaming finished");
|
||||
GST_RTSP_STREAM_UNLOCK (src);
|
||||
/* waiting for connection idle, we were flushing so any attempt at doing data
|
||||
* transfer will result in pausing the tasks. */
|
||||
GST_DEBUG_OBJECT (src, "wait for connection idle");
|
||||
GST_RTSP_CONN_LOCK (src);
|
||||
GST_DEBUG_OBJECT (src, "connection is idle now");
|
||||
GST_RTSP_CONN_UNLOCK (src);
|
||||
|
||||
GST_DEBUG_OBJECT (src, "stop connection flush");
|
||||
gst_rtsp_connection_flush (src->connection, FALSE);
|
||||
|
|
|
@ -78,6 +78,10 @@ typedef struct _GstRTSPSrcClass GstRTSPSrcClass;
|
|||
#define GST_RTSP_STREAM_LOCK(rtsp) (g_static_rec_mutex_lock (GST_RTSP_STREAM_GET_LOCK(rtsp)))
|
||||
#define GST_RTSP_STREAM_UNLOCK(rtsp) (g_static_rec_mutex_unlock (GST_RTSP_STREAM_GET_LOCK(rtsp)))
|
||||
|
||||
#define GST_RTSP_CONN_GET_LOCK(rtsp) (GST_RTSPSRC_CAST(rtsp)->conn_rec_lock)
|
||||
#define GST_RTSP_CONN_LOCK(rtsp) (g_static_rec_mutex_lock (GST_RTSP_CONN_GET_LOCK(rtsp)))
|
||||
#define GST_RTSP_CONN_UNLOCK(rtsp) (g_static_rec_mutex_unlock (GST_RTSP_CONN_GET_LOCK(rtsp)))
|
||||
|
||||
typedef struct _GstRTSPStream GstRTSPStream;
|
||||
|
||||
struct _GstRTSPStream {
|
||||
|
@ -138,6 +142,9 @@ struct _GstRTSPSrc {
|
|||
/* mutex for protecting state changes */
|
||||
GStaticRecMutex *state_rec_lock;
|
||||
|
||||
/* mutex for protecting the connection */
|
||||
GStaticRecMutex *conn_rec_lock;
|
||||
|
||||
gint numstreams;
|
||||
GList *streams;
|
||||
GstStructure *props;
|
||||
|
|
Loading…
Reference in a new issue