From: W.C.A. Wijngaards Date: Thu, 21 Mar 2024 14:06:38 +0000 (+0100) Subject: - fast-reload, option for fast-reload commandline, +p does not pause threads. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c97f5a6df2219f3a39a764e5fe08d46dd6b422c2;p=thirdparty%2Funbound.git - fast-reload, option for fast-reload commandline, +p does not pause threads. --- diff --git a/daemon/remote.c b/daemon/remote.c index ecd30af27..5ee3d4d32 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -674,6 +674,39 @@ do_reload(RES* ssl, struct worker* worker, int reuse_cache) send_ok(ssl); } +#ifndef THREADS_DISABLED +/** parse fast reload command options. */ +static int +fr_parse_options(RES* ssl, char* arg, int* fr_verb, int* fr_nopause) +{ + char* argp = arg; + while(*argp=='+') { + argp++; + while(*argp!=0 && *argp!=' ' && *argp!='\t') { + if(*argp == 'v') { + (*fr_verb)++; + } else if(*argp == 'p') { + (*fr_nopause) = 1; + } else { + if(!ssl_printf(ssl, + "error: unknown option '+%c'\n", + *argp)) + return 0; + return 0; + } + argp++; + } + argp = skipwhite(argp); + } + if(*argp!=0) { + if(!ssl_printf(ssl, "error: unknown option '%s'\n", argp)) + return 0; + return 0; + } + return 1; +} +#endif /* !THREADS_DISABLED */ + /** do the fast_reload command */ static void do_fast_reload(RES* ssl, struct worker* worker, struct rc_state* s, char* arg) @@ -685,27 +718,14 @@ do_fast_reload(RES* ssl, struct worker* worker, struct rc_state* s, char* arg) (void)s; (void)arg; #else - int fr_verb = 0; - if(arg[0] == '+') { - int i=1; - while(arg[i]!=0 && arg[i]!=' ' && arg[i]!='\t') { - if(arg[i] == 'v') - fr_verb++; - else { - if(!ssl_printf(ssl, - "error: unknown option '+%c'\n", - arg[i])) - return; - return; - } - i++; - } - } + int fr_verb = 0, fr_nopause = 0; + if(!fr_parse_options(ssl, arg, &fr_verb, &fr_nopause)) + return; if(fr_verb >= 1) { if(!ssl_printf(ssl, "start fast_reload\n")) return; } - fast_reload_thread_start(ssl, worker, s, fr_verb); + fast_reload_thread_start(ssl, worker, s, fr_verb, fr_nopause); #endif } @@ -4244,12 +4264,16 @@ fr_reload_ipc(struct fast_reload_thread* fr, struct config_file* newcfg, struct fast_reload_construct* ct) { int result = 1; - fr_send_notification(fr, fast_reload_notification_reload_stop); - fr_poll_for_ack(fr); + if(!fr->fr_nopause) { + fr_send_notification(fr, fast_reload_notification_reload_stop); + fr_poll_for_ack(fr); + } if(!fr_reload_config(fr, newcfg, ct)) { result = 0; } - fr_send_notification(fr, fast_reload_notification_reload_start); + if(!fr->fr_nopause) { + fr_send_notification(fr, fast_reload_notification_reload_start); + } return result; } @@ -4653,7 +4677,7 @@ create_socketpair(int* pair, struct ub_randstate* rand) /** fast reload thread. setup the thread info */ static int -fast_reload_thread_setup(struct worker* worker, int fr_verb) +fast_reload_thread_setup(struct worker* worker, int fr_verb, int fr_nopause) { struct fast_reload_thread* fr; int numworkers = worker->daemon->num; @@ -4663,6 +4687,7 @@ fast_reload_thread_setup(struct worker* worker, int fr_verb) return 0; fr = worker->daemon->fast_reload_thread; fr->fr_verb = fr_verb; + fr->fr_nopause = fr_nopause; /* The thread id printed in logs, numworker+1 is the dnstap thread. * This is numworkers+2. */ fr->threadnum = numworkers+2; @@ -5407,13 +5432,13 @@ fr_send_stop(struct fast_reload_thread* fr) void fast_reload_thread_start(RES* ssl, struct worker* worker, struct rc_state* s, - int fr_verb) + int fr_verb, int fr_nopause) { if(worker->daemon->fast_reload_thread) { log_err("fast reload thread already running"); return; } - if(!fast_reload_thread_setup(worker, fr_verb)) { + if(!fast_reload_thread_setup(worker, fr_verb, fr_nopause)) { if(!ssl_printf(ssl, "error could not setup thread\n")) return; return; diff --git a/daemon/remote.h b/daemon/remote.h index d508385ba..0c7209e51 100644 --- a/daemon/remote.h +++ b/daemon/remote.h @@ -189,6 +189,8 @@ struct fast_reload_thread { int need_to_quit; /** verbosity of the fast_reload command, the number of +v options */ int fr_verb; + /** option to not pause threads during reload */ + int fr_nopause; /** the event that listens on the remote service worker to the * commpair, it receives content from the fast reload thread. */ @@ -313,9 +315,10 @@ int ssl_read_line(RES* ssl, char* buf, size_t max); * while the fast reload is running. * @param fr_verb: verbosity to print output at. 0 is nothing, 1 is some * and 2 is more detail. + * @param fr_nopause: option to not pause threads during reload. */ void fast_reload_thread_start(RES* ssl, struct worker* worker, - struct rc_state* s, int fr_verb); + struct rc_state* s, int fr_verb, int fr_nopause); /** * Stop fast reload thread diff --git a/doc/unbound-control.8.in b/doc/unbound-control.8.in index 901636c11..c2df9e182 100644 --- a/doc/unbound-control.8.in +++ b/doc/unbound-control.8.in @@ -60,7 +60,7 @@ Reload the server but try to keep the RRset and message cache if That means the caches sizes and the number of threads must not change between reloads. .TP -.B fast_reload \fR[\fI+v\fR] +.B fast_reload \fR[\fI+vp\fR] Reload the server, but keep downtime to a minimum, so that user queries keep seeing service. This needs the code compiled with threads. The config is loaded in a thread, and prepared, then it briefly pauses the existing @@ -74,6 +74,17 @@ That includes the time it took to do the reload. And with more verbose output the amount of memory that was allocated temporarily to perform the reload, this amount of memory can be big if the config has large contents. In the timing output the 'reload' time is the time during which the server was paused. +.IP +The '+p' option makes the reload not pause threads, they keep running. +Locks are acquired, but items are updated in sequence, so it is possible +for threads to see an inconsistent state with some options from the old +and some options from the new config, such as cache TTL parameters from the +old config and forwards from the new config. The stubs and forwards are +updated at the same time, so that they are viewed consistently, either old +or new values together. The option makes the reload time take eg. 3 +microseconds instead of 0.3 milliseconds during which the worker threads are +interrupted. So, the interruption is much shorter, at the expense of some +inconsistency. .TP .B verbosity \fInumber Change verbosity value for logging. Same values as \fBverbosity\fR keyword in diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c index ded85a175..e7f579797 100644 --- a/smallapp/unbound-control.c +++ b/smallapp/unbound-control.c @@ -109,7 +109,7 @@ usage(void) printf(" That means the caches sizes and\n"); printf(" the number of threads must not\n"); printf(" change between reloads.\n"); - printf(" fast_reload [+v] reloads the server but only briefly stops\n"); + printf(" fast_reload [+vp] reloads the server but only briefly stops\n"); printf(" server processing, keeps cache, and only\n"); printf(" changes some options, like forwards\n"); printf(" and stubs.\n");