summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nest/bird.h2
-rw-r--r--nest/proto.c28
-rw-r--r--nest/protocol.h7
-rw-r--r--sysdep/unix/io.c8
-rw-r--r--sysdep/unix/main.c30
-rw-r--r--sysdep/unix/unix.h2
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);