scratch build was tested and fix confirmed. I think we should also reschedule all existing tevent timers, we don't have an infrastructure to do it though.
From 09e5ad3448694d9609bd2a9e89e8a05ef82f66bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrez...@redhat.com>
Date: Mon, 22 Aug 2016 13:15:04 +0200
Subject: [PATCH] watchdog: cope with time shift

Resolves:
https://fedorahosted.org/sssd/ticket/3154
---
 src/util/util_watchdog.c | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/src/util/util_watchdog.c b/src/util/util_watchdog.c
index 5032fddba1b94b3fc7e560162c392dfa57d699cf..178ff92d5c6b950d008620401235474499ba595d 100644
--- a/src/util/util_watchdog.c
+++ b/src/util/util_watchdog.c
@@ -29,8 +29,39 @@ struct watchdog_ctx {
     struct timeval interval;
     struct tevent_timer *te;
     volatile int ticks;
+
+    /* To detect time shift. */
+    struct tevent_context *ev;
+    int input_interval;
+    time_t timestamp;
 } watchdog_ctx;
 
+bool watchdog_detect_timeshift(void)
+{
+    time_t prev_time;
+    time_t cur_time;
+    errno_t ret;
+
+    prev_time = watchdog_ctx.timestamp;
+    cur_time = watchdog_ctx.timestamp = time(NULL);
+    if (cur_time < prev_time) {
+        /* Time shift detected. We need to restart watchdog. */
+        DEBUG(SSSDBG_IMPORTANT_INFO, "Time shift detected, "
+              "restarting watchdog!\n");
+        teardown_watchdog();
+        ret = setup_watchdog(watchdog_ctx.ev, watchdog_ctx.input_interval);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_FATAL_FAILURE, "Unable to restart watchdog "
+                  "[%d]: %s\n", ret, sss_strerror(ret));
+            orderly_shutdown(1);
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
 /* the watchdog is purposefully *not* handled by the tevent
  * signal handler as it is meant to check if the daemon is
  * still processing the event queue itself. A stuck process
@@ -38,6 +69,12 @@ struct watchdog_ctx {
  * signals either */
 static void watchdog_handler(int sig)
 {
+    /* Do not count ticks if time shift was detected
+     * since watchdog was restarted. */
+    if (watchdog_detect_timeshift()) {
+        return;
+    }
+
     /* if 3 ticks passed by kills itself */
 
     if (__sync_add_and_fetch(&watchdog_ctx.ticks, 1) > 3) {
@@ -101,6 +138,10 @@ int setup_watchdog(struct tevent_context *ev, int interval)
     watchdog_ctx.interval.tv_sec = interval;
     watchdog_ctx.interval.tv_usec = 0;
 
+    watchdog_ctx.ev = ev;
+    watchdog_ctx.input_interval = interval;
+    watchdog_ctx.timestamp = time(NULL);
+
     /* Start the timer */
     /* we give 1 second head start to the watchdog event */
     its.it_value.tv_sec = interval + 1;
-- 
2.1.0

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/admin/lists/sssd-devel@lists.fedorahosted.org

Reply via email to