]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
local: reset daemon after unexpected time jump
authorMiroslav Lichvar <mlichvar@redhat.com>
Mon, 2 Jun 2014 15:14:28 +0000 (17:14 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Mon, 2 Jun 2014 15:38:32 +0000 (17:38 +0200)
Add a new change type and use it when an unexpected time jump is
detected in the scheduler to reset reference times, offset and slewing,
NCR instances (with their polling interval), synchronization status, and
drop all sourcestats, manual, refclock and RTC samples.

This should make the recovery more graceful if the estimated jump has a
large error (e.g. select didn't timeout, or after system suspend).

local.c
local.h
manual.c
ntp_sources.c
refclock.c
reference.c
rtc_linux.c
sources.c
sys_generic.c
test/simulation/005-externalstep

diff --git a/local.c b/local.c
index 3619b589204ccf7b58ed3826095ae50e1521f9b9..513779ebe9da831fd667591cddb5c39a083292e5 100644 (file)
--- a/local.c
+++ b/local.c
@@ -479,7 +479,7 @@ LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked,
     double offset, double dispersion)
 {
   /* Dispatch to all handlers */
-  invoke_parameter_change_handlers(raw, cooked, 0.0, offset, LCL_ChangeStep);
+  invoke_parameter_change_handlers(raw, cooked, 0.0, offset, LCL_ChangeUnknownStep);
 
   lcl_InvokeDispersionNotifyHandlers(dispersion);
 }
diff --git a/local.h b/local.h
index bdf38bd62245c98a606283c431a30ebec2ed2d2f..4000acda60ee1539463176a096586afa278df164 100644 (file)
--- a/local.h
+++ b/local.h
@@ -74,7 +74,8 @@ extern void LCL_GetOffsetCorrection(struct timeval *raw, double *correction, dou
 
 typedef enum {
   LCL_ChangeAdjust,
-  LCL_ChangeStep
+  LCL_ChangeStep,
+  LCL_ChangeUnknownStep
 } LCL_ChangeType;
 
 typedef void (*LCL_ParameterChangeHandler)
index 011d07a1f05db7ec8a5744611320cb4437ca3b84..c286ce875e8c62de93b77493f1e0ad267ef6f657 100644 (file)
--- a/manual.c
+++ b/manual.c
@@ -221,6 +221,11 @@ slew_samples(struct timeval *raw,
 {
   double delta_time;
   int i;
+
+  if (change_type == LCL_ChangeUnknownStep) {
+    MNL_Reset();
+  }
+
   for (i=0; i<n_samples; i++) {
     UTI_AdjustTimeval(&samples[i].when, cooked, &samples[i].when, &delta_time,
         dfreq, doffset);
index 3fa5b2910302c55f0d192049d6eaf14dd4a08f53..87e2e215e96ad20f96f17665f13f4b738558affe 100644 (file)
@@ -491,7 +491,11 @@ slew_sources(struct timeval *raw,
           UTI_IPToString(&records[i].remote_addr->ip_addr), dfreq, doffset);
 #endif
 
-      NCR_SlewTimes(records[i].data, cooked, dfreq, doffset);
+      if (change_type == LCL_ChangeUnknownStep) {
+        NCR_ResetInstance(records[i].data);
+      } else {
+        NCR_SlewTimes(records[i].data, cooked, dfreq, doffset);
+      }
     }
   }
 
index 83b94885d1bb7da1f18b4c82e3d25ab2b0ee242a..d94c73cf0daed9e1606f2388d99145f2c0c1e7b2 100644 (file)
@@ -581,8 +581,12 @@ slew_samples(struct timeval *raw, struct timeval *cooked, double dfreq,
 {
   int i;
 
-  for (i = 0; i < n_sources; i++)
-    filter_slew_samples(&refclocks[i].filter, cooked, dfreq, doffset);
+  for (i = 0; i < n_sources; i++) {
+    if (change_type == LCL_ChangeUnknownStep)
+      filter_reset(&refclocks[i].filter);
+    else
+      filter_slew_samples(&refclocks[i].filter, cooked, dfreq, doffset);
+  }
 }
 
 static void
index 6038ce3d9a44b27f6217bc518a44995ba5a1c28a..503f672c2af49d465b3d90dd32b9602efb38a997 100644 (file)
@@ -147,7 +147,10 @@ handle_slew(struct timeval *raw,
             LCL_ChangeType change_type,
             void *anything)
 {
-  if (change_type == LCL_ChangeStep) {
+  if (change_type == LCL_ChangeUnknownStep) {
+    last_ref_update.tv_sec = 0;
+    last_ref_update.tv_usec = 0;
+  } else if (change_type == LCL_ChangeStep) {
     UTI_AddDoubleToTimeval(&last_ref_update, -doffset, &last_ref_update);
   }
 }
index 602345c5f66a07c2454f2867c3688f38e1124481..88c0160007960a3c3416227c00d915f07723690b 100644 (file)
@@ -273,6 +273,11 @@ slew_samples
   double delta_time;
   double old_seconds_fast, old_gain_rate;
 
+  if (change_type == LCL_ChangeUnknownStep) {
+    /* Drop all samples. */
+    n_samples = 0;
+  }
+
   for (i=0; i<n_samples; i++) {
     UTI_AdjustTimeval(system_times + i, cooked, system_times + i, &delta_time,
         dfreq, doffset);
index d0600ccfde129a5fa1bb6107641882ca20ce1bbd..6ad6bf29b9324579a69934443146ed8c1a62956b 100644 (file)
--- a/sources.c
+++ b/sources.c
@@ -1093,9 +1093,17 @@ slew_sources(struct timeval *raw,
   int i;
 
   for (i=0; i<n_sources; i++) {
-    SST_SlewSamples(sources[i]->stats, cooked, dfreq, doffset);
+    if (change_type == LCL_ChangeUnknownStep) {
+      SST_ResetInstance(sources[i]->stats);
+    } else {
+      SST_SlewSamples(sources[i]->stats, cooked, dfreq, doffset);
+    }
+  }
+
+  if (change_type == LCL_ChangeUnknownStep) {
+    /* After resetting no source is selectable, set reference unsynchronised */
+    SRC_SelectSource(NULL);
   }
-  
 }
 
 /* ================================================== */
index 51c682464c2678dea6ec33288cf833026e010831..2adbbfe0db2caa9392c6fd7113af19591371d743 100644 (file)
@@ -87,6 +87,7 @@ static double slew_error;
 /* ================================================== */
 
 static void handle_end_of_slew(void *anything);
+static void update_slew(void);
 
 /* ================================================== */
 /* Adjust slew_start on clock step */
@@ -95,8 +96,14 @@ static void
 handle_step(struct timeval *raw, struct timeval *cooked, double dfreq,
             double doffset, LCL_ChangeType change_type, void *anything)
 {
-  if (change_type == LCL_ChangeStep)
+  if (change_type == LCL_ChangeUnknownStep) {
+    /* Reset offset and slewing */
+    slew_start = *raw;
+    offset_register = 0.0;
+    update_slew();
+  } else if (change_type == LCL_ChangeStep) {
     UTI_AddDoubleToTimeval(&slew_start, -doffset, &slew_start);
+  }
 }
 
 /* ================================================== */
index 3f263246dbee2e53a5c7c291844c6f5643439aaa..1e5527d1a270b4e926c7c82115d23ece1a6235eb 100755 (executable)
@@ -4,8 +4,8 @@
 
 test_start "external time step"
 
-min_sync_time=1300
-max_sync_time=1500
+min_sync_time=1500
+max_sync_time=1550
 
 for step in -1e2 1e2; do
        # Make one step in 150th second