|
|
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 |
|