chiark / gitweb /
timesyncd: don't busy loop when we cannot connect to any servers
authorLennart Poettering <lennart@poettering.net>
Mon, 5 May 2014 23:29:47 +0000 (01:29 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 5 May 2014 23:29:47 +0000 (01:29 +0200)
src/timesync/timesyncd.c

index 6c88697..bbffbbd 100644 (file)
@@ -39,6 +39,7 @@
 #include "log.h"
 #include "socket-util.h"
 #include "list.h"
 #include "log.h"
 #include "socket-util.h"
 #include "list.h"
+#include "ratelimit.h"
 #include "sd-event.h"
 #include "sd-resolve.h"
 #include "sd-daemon.h"
 #include "sd-event.h"
 #include "sd-resolve.h"
 #include "sd-daemon.h"
  */
 #define OFFSET_1900_1970        2208988800UL
 
  */
 #define OFFSET_1900_1970        2208988800UL
 
+#define RETRY_USEC (30*USEC_PER_SEC)
+#define RATELIMIT_INTERVAL_USEC (10*USEC_PER_SEC)
+#define RATELIMIT_BURST 5
+
 struct ntp_ts {
         be32_t sec;
         be32_t frac;
 struct ntp_ts {
         be32_t sec;
         be32_t frac;
@@ -129,6 +134,8 @@ struct Manager {
 
         LIST_HEAD(ServerName, servers);
 
 
         LIST_HEAD(ServerName, servers);
 
+        RateLimit ratelimit;
+
         /* peer */
         sd_resolve_query *resolve_query;
         sd_event_source *event_receive;
         /* peer */
         sd_resolve_query *resolve_query;
         sd_event_source *event_receive;
@@ -164,6 +171,9 @@ struct Manager {
         sd_event_source *event_clock_watch;
         int clock_watch_fd;
 
         sd_event_source *event_clock_watch;
         int clock_watch_fd;
 
+        /* Retry connections */
+        sd_event_source *event_retry;
+
         /* Handle SIGINT/SIGTERM */
         sd_event_source *sigterm, *sigint;
 };
         /* Handle SIGINT/SIGTERM */
         sd_event_source *sigterm, *sigint;
 };
@@ -847,6 +857,14 @@ static int manager_resolve_handler(sd_resolve_query *q, int ret, const struct ad
         return manager_begin(m);
 }
 
         return manager_begin(m);
 }
 
+static int manager_retry(sd_event_source *source, usec_t usec, void *userdata) {
+        Manager *m = userdata;
+
+        assert(m);
+
+        return manager_connect(m);
+}
+
 static int manager_connect(Manager *m) {
 
         struct addrinfo hints = {
 static int manager_connect(Manager *m) {
 
         struct addrinfo hints = {
@@ -859,6 +877,19 @@ static int manager_connect(Manager *m) {
 
         manager_disconnect(m);
 
 
         manager_disconnect(m);
 
+        m->event_retry = sd_event_source_unref(m->event_retry);
+        if (!ratelimit_test(&m->ratelimit)) {
+                log_debug("Slowing down attempts to contact servers.");
+
+                r = sd_event_add_time(m->event, &m->event_retry, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + RETRY_USEC, 0, manager_retry, m);
+                if (r < 0) {
+                        log_error("Failed to create retry timer: %s", strerror(-r));
+                        return r;
+                }
+
+                return 0;
+        }
+
         /* If we already are operating on some address, switch to the
          * next one. */
         if (m->current_server_address && m->current_server_address->addresses_next)
         /* If we already are operating on some address, switch to the
          * next one. */
         if (m->current_server_address && m->current_server_address->addresses_next)
@@ -939,6 +970,8 @@ static int manager_new(Manager **ret) {
 
         m->server_socket = m->clock_watch_fd = -1;
 
 
         m->server_socket = m->clock_watch_fd = -1;
 
+        RATELIMIT_INIT(m->ratelimit, RATELIMIT_INTERVAL_USEC, RATELIMIT_BURST);
+
         r = sd_event_default(&m->event);
         if (r < 0)
                 return r;
         r = sd_event_default(&m->event);
         if (r < 0)
                 return r;
@@ -974,6 +1007,8 @@ static void manager_free(Manager *m) {
         sd_event_source_unref(m->sigint);
         sd_event_source_unref(m->sigterm);
 
         sd_event_source_unref(m->sigint);
         sd_event_source_unref(m->sigterm);
 
+        sd_event_source_unref(m->event_retry);
+
         sd_resolve_unref(m->resolve);
         sd_event_unref(m->event);
 
         sd_resolve_unref(m->resolve);
         sd_event_unref(m->event);