Blame SOURCES/0116-watchdog-cope-with-time-shift.patch

b2d430
From c99c5bb88c8b02f24a2b0b15ea8bc9fe2a8dc6c4 Mon Sep 17 00:00:00 2001
b2d430
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
b2d430
Date: Mon, 22 Aug 2016 13:15:04 +0200
b2d430
Subject: [PATCH 116/117] watchdog: cope with time shift
b2d430
MIME-Version: 1.0
b2d430
Content-Type: text/plain; charset=UTF-8
b2d430
Content-Transfer-Encoding: 8bit
b2d430
b2d430
When a time is changed into the past during sssd runtime
b2d430
(e.g. on boot during time correction), it is possible that
b2d430
we never hit watchdog tevent timer since it is based on
b2d430
system time.
b2d430
b2d430
This patch adds a past-time shift detection mechanism. If a time
b2d430
shift is detected we restart watchdog.
b2d430
b2d430
Resolves:
b2d430
https://fedorahosted.org/sssd/ticket/3154
b2d430
b2d430
Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
b2d430
Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
b2d430
---
b2d430
 src/util/util_watchdog.c | 41 +++++++++++++++++++++++++++++++++++++++++
b2d430
 1 file changed, 41 insertions(+)
b2d430
b2d430
diff --git a/src/util/util_watchdog.c b/src/util/util_watchdog.c
b2d430
index 5032fddba1b94b3fc7e560162c392dfa57d699cf..1c27d73f13b3042ecb549a2184e1368e8339d199 100644
b2d430
--- a/src/util/util_watchdog.c
b2d430
+++ b/src/util/util_watchdog.c
b2d430
@@ -29,8 +29,39 @@ struct watchdog_ctx {
b2d430
     struct timeval interval;
b2d430
     struct tevent_timer *te;
b2d430
     volatile int ticks;
b2d430
+
b2d430
+    /* To detect time shift. */
b2d430
+    struct tevent_context *ev;
b2d430
+    int input_interval;
b2d430
+    time_t timestamp;
b2d430
 } watchdog_ctx;
b2d430
 
b2d430
+static bool watchdog_detect_timeshift(void)
b2d430
+{
b2d430
+    time_t prev_time;
b2d430
+    time_t cur_time;
b2d430
+    errno_t ret;
b2d430
+
b2d430
+    prev_time = watchdog_ctx.timestamp;
b2d430
+    cur_time = watchdog_ctx.timestamp = time(NULL);
b2d430
+    if (cur_time < prev_time) {
b2d430
+        /* Time shift detected. We need to restart watchdog. */
b2d430
+        DEBUG(SSSDBG_IMPORTANT_INFO, "Time shift detected, "
b2d430
+              "restarting watchdog!\n");
b2d430
+        teardown_watchdog();
b2d430
+        ret = setup_watchdog(watchdog_ctx.ev, watchdog_ctx.input_interval);
b2d430
+        if (ret != EOK) {
b2d430
+            DEBUG(SSSDBG_FATAL_FAILURE, "Unable to restart watchdog "
b2d430
+                  "[%d]: %s\n", ret, sss_strerror(ret));
b2d430
+            orderly_shutdown(1);
b2d430
+        }
b2d430
+
b2d430
+        return true;
b2d430
+    }
b2d430
+
b2d430
+    return false;
b2d430
+}
b2d430
+
b2d430
 /* the watchdog is purposefully *not* handled by the tevent
b2d430
  * signal handler as it is meant to check if the daemon is
b2d430
  * still processing the event queue itself. A stuck process
b2d430
@@ -38,6 +69,12 @@ struct watchdog_ctx {
b2d430
  * signals either */
b2d430
 static void watchdog_handler(int sig)
b2d430
 {
b2d430
+    /* Do not count ticks if time shift was detected
b2d430
+     * since watchdog was restarted. */
b2d430
+    if (watchdog_detect_timeshift()) {
b2d430
+        return;
b2d430
+    }
b2d430
+
b2d430
     /* if 3 ticks passed by kills itself */
b2d430
 
b2d430
     if (__sync_add_and_fetch(&watchdog_ctx.ticks, 1) > 3) {
b2d430
@@ -101,6 +138,10 @@ int setup_watchdog(struct tevent_context *ev, int interval)
b2d430
     watchdog_ctx.interval.tv_sec = interval;
b2d430
     watchdog_ctx.interval.tv_usec = 0;
b2d430
 
b2d430
+    watchdog_ctx.ev = ev;
b2d430
+    watchdog_ctx.input_interval = interval;
b2d430
+    watchdog_ctx.timestamp = time(NULL);
b2d430
+
b2d430
     /* Start the timer */
b2d430
     /* we give 1 second head start to the watchdog event */
b2d430
     its.it_value.tv_sec = interval + 1;
b2d430
-- 
b2d430
2.4.11
b2d430