diff options
-rw-r--r-- | nest/bird.h | 2 | ||||
-rw-r--r-- | nest/proto.c | 28 | ||||
-rw-r--r-- | nest/protocol.h | 7 | ||||
-rw-r--r-- | sysdep/unix/io.c | 8 | ||||
-rw-r--r-- | sysdep/unix/main.c | 30 | ||||
-rw-r--r-- | sysdep/unix/unix.h | 2 |
6 files changed, 75 insertions, 2 deletions
diff --git a/nest/bird.h b/nest/bird.h index 597e2050..b35cd31a 100644 --- a/nest/bird.h +++ b/nest/bird.h @@ -13,4 +13,6 @@ #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 76422e31..f96d37dc 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -28,6 +28,8 @@ 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" }; @@ -178,7 +180,7 @@ proto_rethink_goal(struct proto *p) static void proto_set_goal(struct proto *p, unsigned goal) { - if (p->disabled) + if (p->disabled || shutting_down) goal = FS_HUNGRY; p->core_goal = goal; proto_rethink_goal(p); @@ -195,6 +197,25 @@ protos_start(void) } void +protos_shutdown(void) +{ + struct proto *p, *n; + + debug("Protocol shutdown\n"); + WALK_LIST_DELSAFE(p, n, inactive_proto_list) + if (p->core_state != FS_HUNGRY || p->proto_state != PS_DOWN) + { + proto_shutdown_counter++; + proto_set_goal(p, FS_HUNGRY); + } + WALK_LIST_DELSAFE(p, n, proto_list) + { + proto_shutdown_counter++; + proto_set_goal(p, FS_HUNGRY); + } +} + +void protos_dump_all(void) { struct proto *p; @@ -235,6 +256,8 @@ static void proto_fell_down(struct proto *p) { DBG("Protocol %s down\n", p->name); + if (!--proto_shutdown_counter) + protos_shutdown_notify(); proto_rethink_goal(p); } @@ -291,6 +314,7 @@ proto_notify_state(struct proto *p, unsigned ps) cs = FS_FLUSHING; ev_schedule(proto_flush_event); } + break; default: error: bug("Invalid state transition for %s from %s/%s to */%s", p->name, c_states[cs], p_states[ops], p_states[ps]); @@ -313,6 +337,6 @@ proto_flush_all(void *unused) p->pool = NULL; p->core_state = FS_HUNGRY; proto_relink(p); - proto_rethink_goal(p); + proto_fell_down(p); } } diff --git a/nest/protocol.h b/nest/protocol.h index f6facea6..8a27350c 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -46,6 +46,7 @@ void protos_postconfig(struct config *); void protos_commit(struct config *); void protos_start(void); void protos_dump_all(void); +void protos_shutdown(void); extern list protocol_list; @@ -188,4 +189,10 @@ void proto_notify_state(struct proto *p, unsigned state); extern struct proto_config *cf_dev_proto; +/* + * Callback to sysdep code when shutdown is finished + */ + +void protos_shutdown_notify(void); + #endif diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index d8713f4c..aa4f652a 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -747,11 +747,19 @@ io_loop(void) { async_config(); async_config_flag = 0; + continue; } if (async_dump_flag) { async_dump(); async_dump_flag = 0; + continue; + } + if (async_shutdown_flag) + { + async_shutdown(); + async_shutdown_flag = 0; + continue; } /* And finally enter select() to find active sockets */ diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c index 7b306539..71bb712a 100644 --- a/sysdep/unix/main.c +++ b/sysdep/unix/main.c @@ -26,6 +26,8 @@ #include "unix.h" #include "krt.h" +int shutting_down; + /* * Debugging */ @@ -83,6 +85,24 @@ async_config(void) } /* + * Shutdown + */ + +void +async_shutdown(void) +{ + debug("Shutting down...\n"); + shutting_down = 1; + protos_shutdown(); +} + +void +protos_shutdown_notify(void) +{ + die("System shutdown completed"); +} + +/* * Signals */ @@ -101,6 +121,13 @@ handle_sigusr(int sig) } static void +handle_sigterm(int sig) +{ + debug("Caught SIGTERM...\n"); + async_shutdown_flag = 1; +} + +static void signal_init(void) { struct sigaction sa; @@ -112,6 +139,9 @@ signal_init(void) sa.sa_handler = handle_sighup; sa.sa_flags = SA_RESTART; sigaction(SIGHUP, &sa, NULL); + sa.sa_handler = handle_sigterm; + sa.sa_flags = SA_RESTART; + sigaction(SIGTERM, &sa, NULL); signal(SIGPIPE, SIG_IGN); } diff --git a/sysdep/unix/unix.h b/sysdep/unix/unix.h index a79db2ed..e5271021 100644 --- a/sysdep/unix/unix.h +++ b/sysdep/unix/unix.h @@ -13,11 +13,13 @@ void async_config(void); void async_dump(void); +void async_shutdown(void); /* io.c */ volatile int async_config_flag; volatile int async_dump_flag; +volatile int async_shutdown_flag; void io_init(void); void io_loop(void); |