Introduce a deadline timer that aborts all repository syncs.
authorclaudio <claudio@openbsd.org>
Fri, 2 Sep 2022 21:56:45 +0000 (21:56 +0000)
committerclaudio <claudio@openbsd.org>
Fri, 2 Sep 2022 21:56:45 +0000 (21:56 +0000)
With this rpki-client has a chance to still finish and produce an output
even when a CA is excessivly slow and holds back progress.
With and OK benno@ tb@ and job@

usr.sbin/rpki-client/main.c
usr.sbin/rpki-client/repo.c

index 4a60208..f5e5ab3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: main.c,v 1.217 2022/09/02 19:14:04 claudio Exp $ */
+/*     $OpenBSD: main.c,v 1.218 2022/09/02 21:56:45 claudio Exp $ */
 /*
  * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -66,6 +66,7 @@ int   noop;
 int    filemode;
 int    rrdpon = 1;
 int    repo_timeout;
+time_t deadline;
 
 struct skiplist skiplist = LIST_HEAD_INITIALIZER(skiplist);
 
@@ -1044,6 +1045,10 @@ main(int argc, char *argv[])
                 */
                alarm(timeout);
                signal(SIGALRM, suicide);
+
+               /* give up a bit before the hard timeout and try to finish up */
+               if (!noop)
+                       deadline = getmonotime() + timeout - repo_timeout / 2;
        }
 
        if (pledge("stdio rpath wpath cpath fattr sendfd unveil", NULL) == -1)
index c953d55..84550a9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: repo.c,v 1.38 2022/09/02 19:10:37 claudio Exp $ */
+/*     $OpenBSD: repo.c,v 1.39 2022/09/02 21:56:45 claudio Exp $ */
 /*
  * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -41,6 +41,8 @@ extern struct stats   stats;
 extern int             noop;
 extern int             rrdpon;
 extern int             repo_timeout;
+extern time_t          deadline;
+int                    nofetch;
 
 enum repo_state {
        REPO_LOADING = 0,
@@ -288,7 +290,7 @@ repo_done(const void *vp, int ok)
                if (vp == rp->rsync)
                        entityq_flush(&rp->queue, rp);
                if (vp == rp->rrdp) {
-                       if (!ok) {
+                       if (!ok && !nofetch) {
                                /* try to fall back to rsync */
                                rp->rrdp = NULL;
                                rp->rsync = rsync_get(rp->repouri,
@@ -937,8 +939,8 @@ rrdp_finish(unsigned int id, int ok)
                stats.rrdp_repos++;
                rr->state = REPO_DONE;
        } else {
-               warnx("%s: load from network failed, fallback to rsync",
-                   rr->notifyuri);
+               warnx("%s: load from network failed, fallback to %s",
+                   rr->notifyuri, nofetch ? "cache" : "rsync");
                stats.rrdp_fails++;
                rr->state = REPO_FAILED;
                /* clear the RRDP repo since it failed */
@@ -1044,7 +1046,6 @@ repo_lookup(int talid, const char *uri, const char *notify)
 {
        struct repo     *rp;
        char            *repouri;
-       int              nofetch = 0;
 
        if ((repouri = rsync_base_uri(uri)) == NULL)
                errx(1, "bad caRepository URI: %s", uri);
@@ -1223,8 +1224,26 @@ repo_check_timeout(int timeout)
 {
        struct repo     *rp;
        time_t           now;
+       int              diff;
 
        now = getmonotime();
+
+       /* check against our runtime deadline first */
+       if (deadline != 0) {
+               if (deadline <= now) {
+                       warnx("deadline reached, giving up on repository sync");
+                       nofetch = 1;
+                       /* clear deadline since nofetch is set */
+                       deadline = 0;
+                       /* increase now enough so that all pending repos fail */
+                       now += repo_timeout;
+               } else {
+                       diff = deadline - now;
+                       diff *= 1000;
+                       if (timeout == INFTIM || diff < timeout)
+                               timeout = diff;
+               }
+       }
        /* Look up in repository table. (Lookup should actually fail here) */
        SLIST_FOREACH(rp, &repos, entry) {
                if (repo_state(rp) == REPO_LOADING) {
@@ -1233,7 +1252,7 @@ repo_check_timeout(int timeout)
                                    rp->repouri);
                                repo_abort(rp);
                        } else {
-                               int diff = rp->alarm - now;
+                               diff = rp->alarm - now;
                                diff *= 1000;
                                if (timeout == INFTIM || diff < timeout)
                                        timeout = diff;