From bf8558bc9cab35f31bccd6a55e51f121370765c4 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sun, 16 Jan 2000 17:40:26 +0000 Subject: [PATCH] Converted shutdown to a kind of reconfiguration, it's no more handled as a exception in protocol state machines. Introduced a `shutdown' CLI command. Killed few reconfiguration bugs. --- TODO | 2 -- conf/conf.c | 34 +++++++++++++++++++++++++++++++--- conf/conf.h | 6 ++++++ doc/reply_codes | 5 +++++ nest/bird.h | 4 +--- nest/proto.c | 30 ++++-------------------------- nest/protocol.h | 7 ------- nest/rt-table.c | 4 ++-- sysdep/unix/config.Y | 3 +++ sysdep/unix/main.c | 10 +++++----- 10 files changed, 57 insertions(+), 48 deletions(-) diff --git a/TODO b/TODO index c2a6fc88..e932761a 100644 --- a/TODO +++ b/TODO @@ -30,8 +30,6 @@ Core - config: useless rules when protocols disabled - config: remove protocol startup priority hacks? - config: better datetime format -- config: treat shutdown as reconfiguration to null config? (what about config of logging etc. ?) -- config: fix auto_router_id - krt: rescan interfaces when route addition fails? - krt: does PERSIST mode have any sense if kernel syncer is shut down as last? diff --git a/conf/conf.c b/conf/conf.c index 1c5401bc..c3f52344 100644 --- a/conf/conf.c +++ b/conf/conf.c @@ -25,6 +25,7 @@ static jmp_buf conf_jmpbuf; struct config *config, *new_config, *old_config, *future_config; static event *config_event; +int shutting_down; struct config * config_alloc(byte *name) @@ -100,11 +101,13 @@ config_del_obstacle(struct config *c) } static int -global_commit(struct config *c, struct config *old) +global_commit(struct config *new, struct config *old) { if (!old) return 0; - if (c->router_id != old->router_id) + if (!new->router_id) + new->router_id = old->router_id; + if (new->router_id != old->router_id) return 1; return 0; } @@ -116,7 +119,7 @@ config_do_commit(struct config *c) DBG("do_commit\n"); old_config = config; - config = c; + config = new_config = c; if (old_config) old_config->obstacle_count++; DBG("sysdep_commit\n"); @@ -144,6 +147,8 @@ config_done(void *unused) DBG("config_done\n"); for(;;) { + if (config->shutdown) + sysdep_shutdown_done(); log(L_INFO "Reconfigured"); if (old_config) { @@ -171,6 +176,12 @@ config_commit(struct config *c) } if (old_config) /* Reconfiguration already in progress */ { + if (shutting_down) + { + log(L_INFO "New configuration discarded due to shutdown"); + config_free(c); + return CONF_SHUTDOWN; + } if (future_config) { log(L_INFO "Queueing new configuration, ignoring the one already queued"); @@ -194,6 +205,23 @@ config_commit(struct config *c) return CONF_PROGRESS; } +void +order_shutdown(void) +{ + struct config *c; + + if (shutting_down) + return; + log(L_INFO "Shutting down"); + c = lp_alloc(config->mem, sizeof(struct config)); + memcpy(c, config, sizeof(struct config)); + init_list(&c->protos); + init_list(&c->tables); + c->shutdown = 1; + config_commit(c); + shutting_down = 1; +} + void cf_error(char *msg, ...) { diff --git a/conf/conf.h b/conf/conf.h index 7d13ae9c..9fe133ee 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -27,6 +27,7 @@ struct config { struct symbol **sym_hash; /* Lexer: symbol hash table */ struct symbol **sym_fallback; /* Lexer: fallback symbol hash table */ int obstacle_count; /* Number of items blocking freeing of this config */ + int shutdown; /* This is a pseudo-config for daemon shutdown */ }; /* Please don't use these variables in protocols. Use proto_config->global instead. */ @@ -35,6 +36,8 @@ extern struct config *new_config; /* Configuration being parsed */ extern struct config *old_config; /* Old configuration when reconfiguration is in progress */ extern struct config *future_config; /* New config held here if recon requested during recon */ +extern int shutting_down; + struct config *config_alloc(byte *name); int config_parse(struct config *); int cli_parse(struct config *); @@ -43,10 +46,12 @@ int config_commit(struct config *); void cf_error(char *msg, ...) NORET; void config_add_obstacle(struct config *); void config_del_obstacle(struct config *); +void order_shutdown(void); #define CONF_DONE 0 #define CONF_PROGRESS 1 #define CONF_QUEUED 2 +#define CONF_SHUTDOWN 3 /* Pools */ @@ -98,5 +103,6 @@ int cf_parse(void); void sysdep_preconfig(struct config *); int sysdep_commit(struct config *, struct config *); +void sysdep_shutdown_done(void); #endif diff --git a/doc/reply_codes b/doc/reply_codes index 9b74c5b1..93c3d515 100644 --- a/doc/reply_codes +++ b/doc/reply_codes @@ -11,6 +11,11 @@ Reply codes of BIRD command-line interface 0000 OK 0001 Welcome 0002 Reading configuration +0003 Reconfigured +0004 Reconfiguration in progress +0005 Reconfiguration already in progress, queueing +0006 Reconfiguration ignored, shutting down +0007 Shutdown ordered 1000 BIRD version 1001 Interface list diff --git a/nest/bird.h b/nest/bird.h index b35cd31a..3c7d749b 100644 --- a/nest/bird.h +++ b/nest/bird.h @@ -1,7 +1,7 @@ /* * BIRD Internet Routing Daemon -- Basic Declarations * - * (c) 1998--1999 Martin Mares + * (c) 1998--2000 Martin Mares * * Can be freely distributed and used under the terms of the GNU GPL. */ @@ -13,6 +13,4 @@ #include "lib/birdlib.h" #include "lib/ip.h" -extern int shutting_down; /* The daemon is shutting down */ - #endif diff --git a/nest/proto.c b/nest/proto.c index ecf0d906..36829bfd 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -30,8 +30,6 @@ static list inactive_proto_list; static list initial_proto_list; static list flush_proto_list; -static int proto_shutdown_counter; - static event *proto_flush_event; static char *p_states[] = { "DOWN", "START", "UP", "STOP" }; @@ -221,7 +219,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig) { struct proto *p = oc->proto; struct symbol *sym = cf_find_symbol(oc->name); - if (sym && sym->class == SYM_PROTO) + if (sym && sym->class == SYM_PROTO && !new->shutdown) { /* Found match, let's check if we can smoothly switch to new configuration */ nc = sym->def; @@ -236,7 +234,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig) { /* Generic attributes match, try converting them and then ask the protocol */ p->debug = nc->debug; - if (p->proto->reconfigure(p, nc)) + if (p->proto->reconfigure && p->proto->reconfigure(p, nc)) { DBG("\t%s: same\n", oc->name); p->cf = nc; @@ -247,6 +245,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig) /* Unsuccessful, force reconfig */ DBG("\t%s: power cycling\n", oc->name); p->cf_new = nc; + nc->proto = p; } else { @@ -290,7 +289,7 @@ proto_rethink_goal(struct proto *p) } /* Determine what state we want to reach */ - if (p->disabled || shutting_down || p->reconfiguring) + if (p->disabled || p->reconfiguring) p->core_goal = FS_HUNGRY; else p->core_goal = FS_HAPPY; @@ -320,25 +319,6 @@ proto_rethink_goal(struct proto *p) } } -void -protos_shutdown(void) -{ - struct proto *p, *n; - - debug("Protocol shutdown\n"); - WALK_LIST_BACKWARDS_DELSAFE(p, n, inactive_proto_list) - if (p->core_state != FS_HUNGRY || p->proto_state != PS_DOWN) - { - proto_shutdown_counter++; - proto_rethink_goal(p); - } - WALK_LIST_BACKWARDS_DELSAFE(p, n, proto_list) - { - proto_shutdown_counter++; - proto_rethink_goal(p); - } -} - void protos_dump_all(void) { @@ -389,8 +369,6 @@ proto_fell_down(struct proto *p) { DBG("Protocol %s down\n", p->name); rt_unlock_table(p->table); - if (!--proto_shutdown_counter) - protos_shutdown_notify(); proto_rethink_goal(p); } diff --git a/nest/protocol.h b/nest/protocol.h index 72f88b6b..7c14f972 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -56,7 +56,6 @@ void protos_preconfig(struct config *); void protos_postconfig(struct config *); void protos_commit(struct config *new, struct config *old, int force_restart); void protos_dump_all(void); -void protos_shutdown(void); extern list protocol_list; @@ -251,10 +250,4 @@ struct announce_hook { struct announce_hook *proto_add_announce_hook(struct proto *, struct rtable *); -/* - * Callback to sysdep code when shutdown is finished - */ - -void protos_shutdown_notify(void); - #endif diff --git a/nest/rt-table.c b/nest/rt-table.c index b0d1e291..dcde0af8 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -513,7 +513,7 @@ rt_commit(struct config *new, struct config *old) if (!ot->deleted) { struct symbol *sym = cf_find_symbol(o->name); - if (sym && sym->class == SYM_TABLE) + if (sym && sym->class == SYM_TABLE && !new->shutdown) { DBG("\t%s: same\n", o->name); r = sym->def; @@ -522,7 +522,7 @@ rt_commit(struct config *new, struct config *old) } else { - DBG("\t%s: deleted", o->name); + DBG("\t%s: deleted\n", o->name); ot->deleted = old; config_add_obstacle(old); rt_lock_table(ot); diff --git a/sysdep/unix/config.Y b/sysdep/unix/config.Y index 299cc41d..cd553f8e 100644 --- a/sysdep/unix/config.Y +++ b/sysdep/unix/config.Y @@ -67,6 +67,9 @@ log_cat: CF_CLI(CONFIGURE, cfg_name, [], [[Reload configuration]]) { cmd_reconfig($2); } ; +CF_CLI(SHUTDOWN,,, [[Shut the daemon down]]) +{ cli_msg(7, "Shutdown ordered"); order_shutdown(); } ; + cfg_name: /* empty */ { $$ = NULL; } | TEXT diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c index 97b9dc60..5019a3d5 100644 --- a/sysdep/unix/main.c +++ b/sysdep/unix/main.c @@ -29,8 +29,6 @@ #include "unix.h" #include "krt.h" -int shutting_down; - /* * Debugging */ @@ -153,6 +151,9 @@ cmd_reconfig(char *name) case CONF_PROGRESS: cli_msg(4, "Reconfiguration in progress."); break; + case CONF_SHUTDOWN: + cli_msg(6, "Reconfiguration ignored, shutting down."); + break; default: cli_msg(5, "Reconfiguration already in progress, queueing new config"); } @@ -275,12 +276,11 @@ void async_shutdown(void) { debug("Shutting down...\n"); - shutting_down = 1; - protos_shutdown(); + order_shutdown(); } void -protos_shutdown_notify(void) +sysdep_shutdown_done(void) { unlink(PATH_CONTROL_SOCKET); die("System shutdown completed");