[ISC-Bugs #34784]
- Added support for gentle shutdown after signal is received.
- [ISC-BUGS #32692]
+ [ISC-Bugs #32692] [ISC-Bugs 34945]
- Enhance the DHCPv6 server logging to include the addresses that are assigned
to the clients.
/* Start dispatching packets and timeouts... */
dispatch();
+ /* In fact dispatch() never returns. */
return 0;
}
struct client_state *client;
struct timeval tv;
+ if (newstate == server_shutdown) {
+ /* Re-entry */
+ if (shutdown_signal == SIGUSR1)
+ return ISC_R_SUCCESS;
+ /* Log shutdown on signal. */
+ if ((shutdown_signal == SIGINT) ||
+ (shutdown_signal == SIGTERM)) {
+ log_info("Received signal %d, initiating shutdown.",
+ shutdown_signal);
+ }
+ /* Mark it was called. */
+ shutdown_signal = SIGUSR1;
+ }
+
/* Do the right thing for each interface. */
for (ip = interfaces; ip; ip = ip -> next) {
for (client = ip -> client; client; client = client -> next) {
{
isc_result_t status;
- status = isc_app_ctxrun(dhcp_gbl_ctx.actx);
+ do {
+ status = isc_app_ctxrun(dhcp_gbl_ctx.actx);
- /*
- * isc_app_ctxrun can be stopped by receiving a signal. It will
- * return ISC_R_SUCCESS in that case. That is a normal behavior.
- */
+ /*
+ * isc_app_ctxrun can be stopped by receiving a
+ * signal. It will return ISC_R_RELOAD in that
+ * case. That is a normal behavior.
+ */
- if (status != ISC_R_SUCCESS) {
- log_fatal ("Dispatch routine failed: %s -- exiting",
- isc_result_totext (status));
- }
+ if (status == ISC_R_RELOAD) {
+ /*
+ * dhcp_set_control_state() will do the job.
+ * Note its first argument is ignored.
+ */
+ status = dhcp_set_control_state(server_shutdown,
+ server_shutdown);
+ if (status == ISC_R_SUCCESS)
+ status = ISC_R_RELOAD;
+ }
+ } while (status == ISC_R_RELOAD);
+
+ log_fatal ("Dispatch routine failed: %s -- exiting",
+ isc_result_totext (status));
}
void
isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
control_object_state_t newstate)
{
- return ISC_R_SUCCESS;
+ if (newstate != server_shutdown)
+ return ISC_R_SUCCESS;
+ exit (0);
}
void isclib_cleanup(void);
void dhcp_signal_handler(int signal);
+extern int shutdown_signal;
#endif /* ISCLIB_H */
#include <signal.h>
dhcp_context_t dhcp_gbl_ctx;
+int shutdown_signal = 0;
void
isclib_cleanup(void)
*/
void dhcp_signal_handler(int signal) {
isc_appctx_t *ctx = dhcp_gbl_ctx.actx;
- if (ctx && ctx->methods && ctx->methods->ctxshutdown) {
- /*
- * Let's not use standard log facilities here. They may not be
- * signal safe, e.g. we could get the signal in the middle of
- * another log call
- */
- printf("Received signal %d, initiating shutdown.\n", signal);
- ctx->methods->ctxshutdown(ctx);
+ int prev = shutdown_signal;
+
+ if (prev != 0) {
+ /* Already in shutdown. */
+ return;
+ }
+ /* Possible race but does it matter? */
+ shutdown_signal = signal;
+
+ /* Use reload (aka suspend) for easier dispatch() reenter. */
+ if (ctx && ctx->methods && ctx->methods->ctxsuspend) {
+ (void) isc_app_ctxsuspend(ctx);
}
}
/* Start dispatching packets and timeouts... */
dispatch();
+ /* In fact dispatch() never returns. */
return (0);
}
isc_result_t
dhcp_set_control_state(control_object_state_t oldstate,
control_object_state_t newstate) {
- return ISC_R_SUCCESS;
+ if (newstate != server_shutdown)
+ return ISC_R_SUCCESS;
+ exit(0);
}
/*
* Receive packets and dispatch them...
- * dispatch() will return only when we are shutting down.
+ * dispatch() will never return.
*/
dispatch ();
- log_info("Shutting down.");
- dhcp_set_control_state(server_shutdown/*ignored*/, server_shutdown);
-
/* Let's return status code */
return 0;
}
isc_result_t dhcp_set_control_state (control_object_state_t oldstate,
control_object_state_t newstate)
{
- if (newstate == server_shutdown) {
- shutdown_time = cur_time;
- shutdown_state = shutdown_listeners;
+ struct timeval tv;
+
+ if (newstate != server_shutdown)
+ return DHCP_R_INVALIDARG;
+ /* Re-entry. */
+ if (shutdown_signal == SIGUSR1)
+ return ISC_R_SUCCESS;
+ shutdown_time = cur_time;
+ shutdown_state = shutdown_listeners;
+ /* Called by user. */
+ if (shutdown_signal == 0) {
+ shutdown_signal = SIGUSR1;
dhcp_io_shutdown_countdown (0);
return ISC_R_SUCCESS;
}
- return DHCP_R_INVALIDARG;
+ /* Called on signal. */
+ log_info("Received signal %d, initiating shutdown.", shutdown_signal);
+ shutdown_signal = SIGUSR1;
+
+ /*
+ * Prompt the shutdown event onto the timer queue
+ * and return to the dispatch loop.
+ */
+ tv.tv_sec = cur_tv.tv_sec;
+ tv.tv_usec = cur_tv.tv_usec + 1;
+ add_timeout(&tv,
+ (void (*)(void *))dhcp_io_shutdown_countdown, 0, 0, 0);
+ return ISC_R_SUCCESS;
}