Perform gracious shutdown upon receipt of SIGTERM. Finally we can

test the whole protocol shutdown code... :)
This commit is contained in:
Martin Mares 1999-02-13 20:15:36 +00:00
parent 7f3d1a0850
commit f4aabcee62
6 changed files with 75 additions and 2 deletions

View file

@ -13,4 +13,6 @@
#include "lib/birdlib.h" #include "lib/birdlib.h"
#include "lib/ip.h" #include "lib/ip.h"
extern int shutting_down; /* The daemon is shutting down */
#endif #endif

View file

@ -28,6 +28,8 @@ static list inactive_proto_list;
static list initial_proto_list; static list initial_proto_list;
static list flush_proto_list; static list flush_proto_list;
static int proto_shutdown_counter;
static event *proto_flush_event; static event *proto_flush_event;
static char *p_states[] = { "DOWN", "START", "UP", "STOP" }; static char *p_states[] = { "DOWN", "START", "UP", "STOP" };
@ -178,7 +180,7 @@ proto_rethink_goal(struct proto *p)
static void static void
proto_set_goal(struct proto *p, unsigned goal) proto_set_goal(struct proto *p, unsigned goal)
{ {
if (p->disabled) if (p->disabled || shutting_down)
goal = FS_HUNGRY; goal = FS_HUNGRY;
p->core_goal = goal; p->core_goal = goal;
proto_rethink_goal(p); proto_rethink_goal(p);
@ -194,6 +196,25 @@ protos_start(void)
proto_set_goal(p, FS_HAPPY); proto_set_goal(p, FS_HAPPY);
} }
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 void
protos_dump_all(void) protos_dump_all(void)
{ {
@ -235,6 +256,8 @@ static void
proto_fell_down(struct proto *p) proto_fell_down(struct proto *p)
{ {
DBG("Protocol %s down\n", p->name); DBG("Protocol %s down\n", p->name);
if (!--proto_shutdown_counter)
protos_shutdown_notify();
proto_rethink_goal(p); proto_rethink_goal(p);
} }
@ -291,6 +314,7 @@ proto_notify_state(struct proto *p, unsigned ps)
cs = FS_FLUSHING; cs = FS_FLUSHING;
ev_schedule(proto_flush_event); ev_schedule(proto_flush_event);
} }
break;
default: default:
error: error:
bug("Invalid state transition for %s from %s/%s to */%s", p->name, c_states[cs], p_states[ops], p_states[ps]); 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->pool = NULL;
p->core_state = FS_HUNGRY; p->core_state = FS_HUNGRY;
proto_relink(p); proto_relink(p);
proto_rethink_goal(p); proto_fell_down(p);
} }
} }

View file

@ -46,6 +46,7 @@ void protos_postconfig(struct config *);
void protos_commit(struct config *); void protos_commit(struct config *);
void protos_start(void); void protos_start(void);
void protos_dump_all(void); void protos_dump_all(void);
void protos_shutdown(void);
extern list protocol_list; extern list protocol_list;
@ -188,4 +189,10 @@ void proto_notify_state(struct proto *p, unsigned state);
extern struct proto_config *cf_dev_proto; extern struct proto_config *cf_dev_proto;
/*
* Callback to sysdep code when shutdown is finished
*/
void protos_shutdown_notify(void);
#endif #endif

View file

@ -747,11 +747,19 @@ io_loop(void)
{ {
async_config(); async_config();
async_config_flag = 0; async_config_flag = 0;
continue;
} }
if (async_dump_flag) if (async_dump_flag)
{ {
async_dump(); async_dump();
async_dump_flag = 0; async_dump_flag = 0;
continue;
}
if (async_shutdown_flag)
{
async_shutdown();
async_shutdown_flag = 0;
continue;
} }
/* And finally enter select() to find active sockets */ /* And finally enter select() to find active sockets */

View file

@ -26,6 +26,8 @@
#include "unix.h" #include "unix.h"
#include "krt.h" #include "krt.h"
int shutting_down;
/* /*
* Debugging * Debugging
*/ */
@ -82,6 +84,24 @@ async_config(void)
debug("Asynchronous reconfigurations are not supported in demo version\n"); debug("Asynchronous reconfigurations are not supported in demo version\n");
} }
/*
* Shutdown
*/
void
async_shutdown(void)
{
debug("Shutting down...\n");
shutting_down = 1;
protos_shutdown();
}
void
protos_shutdown_notify(void)
{
die("System shutdown completed");
}
/* /*
* Signals * Signals
*/ */
@ -100,6 +120,13 @@ handle_sigusr(int sig)
async_dump_flag = 1; async_dump_flag = 1;
} }
static void
handle_sigterm(int sig)
{
debug("Caught SIGTERM...\n");
async_shutdown_flag = 1;
}
static void static void
signal_init(void) signal_init(void)
{ {
@ -112,6 +139,9 @@ signal_init(void)
sa.sa_handler = handle_sighup; sa.sa_handler = handle_sighup;
sa.sa_flags = SA_RESTART; sa.sa_flags = SA_RESTART;
sigaction(SIGHUP, &sa, NULL); sigaction(SIGHUP, &sa, NULL);
sa.sa_handler = handle_sigterm;
sa.sa_flags = SA_RESTART;
sigaction(SIGTERM, &sa, NULL);
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
} }

View file

@ -13,11 +13,13 @@
void async_config(void); void async_config(void);
void async_dump(void); void async_dump(void);
void async_shutdown(void);
/* io.c */ /* io.c */
volatile int async_config_flag; volatile int async_config_flag;
volatile int async_dump_flag; volatile int async_dump_flag;
volatile int async_shutdown_flag;
void io_init(void); void io_init(void);
void io_loop(void); void io_loop(void);