rtsp-session: Use monotonic time for RTSP session timeout

Changed RTSP session timeout handling to monotonic time
and deprecating the API for current system time.

This fixes timeouts when the system time changes.

https://bugzilla.gnome.org/show_bug.cgi?id=743346
This commit is contained in:
Kent-Inge Ingesson 2015-02-19 10:43:16 +02:00 committed by Sebastian Dröge
parent 51ed357597
commit d2f1997c4b
3 changed files with 106 additions and 14 deletions

View file

@ -470,7 +470,7 @@ gst_rtsp_session_pool_remove (GstRTSPSessionPool * pool, GstRTSPSession * sess)
typedef struct
{
GTimeVal now;
gint64 now_monotonic_time;
GstRTSPSessionPool *pool;
GList *removed;
} CleanupData;
@ -480,11 +480,13 @@ cleanup_func (gchar * sessionid, GstRTSPSession * sess, CleanupData * data)
{
gboolean expired;
expired = gst_rtsp_session_is_expired (sess, &data->now);
expired = gst_rtsp_session_is_expired_usec (sess, data->now_monotonic_time);
if (expired) {
GST_DEBUG ("session expired");
data->removed = g_list_prepend (data->removed, g_object_ref (sess));
}
return expired;
}
@ -509,7 +511,8 @@ gst_rtsp_session_pool_cleanup (GstRTSPSessionPool * pool)
priv = pool->priv;
g_get_current_time (&data.now);
data.now_monotonic_time = g_get_monotonic_time ();
data.pool = pool;
data.removed = NULL;
@ -661,11 +664,12 @@ static void
collect_timeout (gchar * sessionid, GstRTSPSession * sess, GstPoolSource * psrc)
{
gint timeout;
GTimeVal now;
gint64 now_monotonic_time;
g_get_current_time (&now);
now_monotonic_time = g_get_monotonic_time ();
timeout = gst_rtsp_session_next_timeout_usec (sess, now_monotonic_time);
timeout = gst_rtsp_session_next_timeout (sess, &now);
GST_INFO ("%p: next timeout: %d", sess, timeout);
if (psrc->timeout == -1 || timeout < psrc->timeout)
psrc->timeout = timeout;

View file

@ -57,9 +57,9 @@ struct _GstRTSPSessionPrivate
guint timeout;
gboolean timeout_always_visible;
GTimeVal create_time; /* immutable */
GMutex last_access_lock;
GTimeVal last_access;
gint64 last_access_monotonic_time;
gint64 last_access_real_time;
gint expire_count;
GList *medias;
@ -135,7 +135,7 @@ gst_rtsp_session_init (GstRTSPSession * session)
g_mutex_init (&priv->lock);
g_mutex_init (&priv->last_access_lock);
priv->timeout = DEFAULT_TIMEOUT;
g_get_current_time (&priv->create_time);
gst_rtsp_session_touch (session);
}
@ -559,7 +559,8 @@ gst_rtsp_session_touch (GstRTSPSession * session)
priv = session->priv;
g_mutex_lock (&priv->last_access_lock);
g_get_current_time (&priv->last_access);
priv->last_access_monotonic_time = g_get_monotonic_time ();
priv->last_access_real_time = g_get_real_time ();
g_mutex_unlock (&priv->last_access_lock);
}
@ -590,6 +591,52 @@ gst_rtsp_session_allow_expire (GstRTSPSession * session)
g_atomic_int_add (&session->priv->expire_count, -1);
}
/**
* gst_rtsp_session_next_timeout_usec:
* @session: a #GstRTSPSession
* @now: (transfer none): the current monotonic time
*
* Get the amount of milliseconds till the session will expire.
*
* Returns: the amount of milliseconds since the session will time out.
*/
gint
gst_rtsp_session_next_timeout_usec (GstRTSPSession * session, gint64 now)
{
GstRTSPSessionPrivate *priv;
gint res;
GstClockTime last_access, now_ns;
g_return_val_if_fail (GST_IS_RTSP_SESSION (session), -1);
priv = session->priv;
g_mutex_lock (&priv->last_access_lock);
if (g_atomic_int_get (&priv->expire_count) != 0) {
/* touch session when the expire count is not 0 */
priv->last_access_monotonic_time = g_get_monotonic_time ();
priv->last_access_real_time = g_get_real_time ();
}
last_access = GST_USECOND * (priv->last_access_monotonic_time);
/* add timeout allow for 5 seconds of extra time */
last_access += priv->timeout * GST_SECOND + (5 * GST_SECOND);
g_mutex_unlock (&priv->last_access_lock);
now_ns = GST_USECOND * now;
if (last_access > now_ns) {
res = GST_TIME_AS_MSECONDS (last_access - now_ns);
} else {
res = 0;
}
return res;
}
/****** Deprecated API *******/
/**
* gst_rtsp_session_next_timeout:
* @session: a #GstRTSPSession
@ -598,7 +645,11 @@ gst_rtsp_session_allow_expire (GstRTSPSession * session)
* Get the amount of milliseconds till the session will expire.
*
* Returns: the amount of milliseconds since the session will time out.
*
* Deprecated: Use gst_rtsp_session_next_timeout_usec() instead.
*/
#ifndef GST_REMOVE_DEPRECATED
#ifndef GST_DISABLE_DEPRECATED
gint
gst_rtsp_session_next_timeout (GstRTSPSession * session, GTimeVal * now)
{
@ -614,23 +665,50 @@ gst_rtsp_session_next_timeout (GstRTSPSession * session, GTimeVal * now)
g_mutex_lock (&priv->last_access_lock);
if (g_atomic_int_get (&priv->expire_count) != 0) {
/* touch session when the expire count is not 0 */
g_get_current_time (&priv->last_access);
priv->last_access_monotonic_time = g_get_monotonic_time ();
priv->last_access_real_time = g_get_real_time ();
}
last_access = GST_TIMEVAL_TO_TIME (priv->last_access);
last_access = GST_USECOND * (priv->last_access_real_time);
/* add timeout allow for 5 seconds of extra time */
last_access += priv->timeout * GST_SECOND + (5 * GST_SECOND);
g_mutex_unlock (&priv->last_access_lock);
now_ns = GST_TIMEVAL_TO_TIME (*now);
if (last_access > now_ns)
if (last_access > now_ns) {
res = GST_TIME_AS_MSECONDS (last_access - now_ns);
else
} else {
res = 0;
}
return res;
}
#endif
#endif
/**
* gst_rtsp_session_is_expired_usec:
* @session: a #GstRTSPSession
* @now: (transfer none): the current monotonic time
*
* Check if @session timeout out.
*
* Returns: %TRUE if @session timed out
*/
gboolean
gst_rtsp_session_is_expired_usec (GstRTSPSession * session, gint64 now)
{
gboolean res;
res = (gst_rtsp_session_next_timeout_usec (session, now) == 0);
return res;
}
/****** Deprecated API *******/
/**
* gst_rtsp_session_is_expired:
@ -640,7 +718,11 @@ gst_rtsp_session_next_timeout (GstRTSPSession * session, GTimeVal * now)
* Check if @session timeout out.
*
* Returns: %TRUE if @session timed out
*
* Deprecated: Use gst_rtsp_session_is_expired_usec() instead.
*/
#ifndef GST_REMOVE_DEPRECATED
#ifndef GST_DISABLE_DEPRECATED
gboolean
gst_rtsp_session_is_expired (GstRTSPSession * session, GTimeVal * now)
{
@ -650,3 +732,5 @@ gst_rtsp_session_is_expired (GstRTSPSession * session, GTimeVal * now)
return res;
}
#endif
#endif

View file

@ -95,8 +95,12 @@ guint gst_rtsp_session_get_timeout (GstRTSPSession *se
void gst_rtsp_session_touch (GstRTSPSession *session);
void gst_rtsp_session_prevent_expire (GstRTSPSession *session);
void gst_rtsp_session_allow_expire (GstRTSPSession *session);
gint gst_rtsp_session_next_timeout_usec (GstRTSPSession *session, gint64 now);
gboolean gst_rtsp_session_is_expired_usec (GstRTSPSession *session, gint64 now);
#ifndef GST_DISABLE_DEPRECATED
gint gst_rtsp_session_next_timeout (GstRTSPSession *session, GTimeVal *now);
gboolean gst_rtsp_session_is_expired (GstRTSPSession *session, GTimeVal *now);
#endif
/* handle media in a session */
GstRTSPSessionMedia * gst_rtsp_session_manage_media (GstRTSPSession *sess,