summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Routhier <sar@isc.org>2013-10-30 13:52:36 -0700
committerShawn Routhier <sar@isc.org>2013-10-30 13:52:36 -0700
commit47e8308dea6ee44ce19edf4fdf3331fa41a986f7 (patch)
treec2801fff3fff0639b504de72675ea62b0d1cab65
parent58cb5d861d6f412475722381723dc788c314c39f (diff)
downloadisc-dhcp-47e8308dea6ee44ce19edf4fdf3331fa41a986f7.tar.gz
[master]
[32692] Signal handlers added: sigint (ctrl-c) and sigterm (default kill)
-rw-r--r--RELNOTES3
-rw-r--r--client/dhclient.c6
-rw-r--r--common/dispatch.c13
-rw-r--r--includes/omapip/isclib.h4
-rw-r--r--omapip/dispatch.c60
-rw-r--r--omapip/isclib.c20
-rw-r--r--relay/dhcrelay.c6
-rw-r--r--server/dhcpd.c16
8 files changed, 110 insertions, 18 deletions
diff --git a/RELNOTES b/RELNOTES
index 3e7350d5..6c1ec679 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -129,6 +129,9 @@ work on other platforms. Please report any problems and suggested fixes to
for the bug report and a potential patch.
[ISC-Bugs #34784]
+- Added support for gentle shutdown after signal is received.
+ [ISC-BUGS #32692]
+
Changes since 4.2.4
- Correct code to calculate timing values in client to compare
diff --git a/client/dhclient.c b/client/dhclient.c
index c303f7e3..f131e393 100644
--- a/client/dhclient.c
+++ b/client/dhclient.c
@@ -691,6 +691,10 @@ main(int argc, char **argv) {
dmalloc_outstanding = 0;
#endif
+ /* install signal handlers */
+ signal(SIGINT, dhcp_signal_handler); /* control-c */
+ signal(SIGTERM, dhcp_signal_handler); /* kill */
+
/* If we're not supposed to wait before getting the address,
don't. */
if (nowait)
@@ -704,7 +708,6 @@ main(int argc, char **argv) {
/* Start dispatching packets and timeouts... */
dispatch();
- /*NOTREACHED*/
return 0;
}
@@ -807,7 +810,6 @@ void run_stateless(int exit_mode)
/* Start dispatching packets and timeouts... */
dispatch();
- /*NOTREACHED*/
#endif /* DHCPv6 */
return;
}
diff --git a/common/dispatch.c b/common/dispatch.c
index 7c4434e7..976d37e2 100644
--- a/common/dispatch.c
+++ b/common/dispatch.c
@@ -3,7 +3,7 @@
Network input dispatcher... */
/*
- * Copyright (c) 2004-2011 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2011,2013 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1995-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
@@ -112,8 +112,15 @@ dispatch(void)
status = isc_app_ctxrun(dhcp_gbl_ctx.actx);
- log_fatal ("Dispatch routine failed: %s -- exiting",
- isc_result_totext (status));
+ /*
+ * isc_app_ctxrun can be stopped by receiving a signal. It will
+ * return ISC_R_SUCCESS in that case. That is a normal behavior.
+ */
+
+ if (status != ISC_R_SUCCESS) {
+ log_fatal ("Dispatch routine failed: %s -- exiting",
+ isc_result_totext (status));
+ }
}
void
diff --git a/includes/omapip/isclib.h b/includes/omapip/isclib.h
index ddefeb5f..7fd30fea 100644
--- a/includes/omapip/isclib.h
+++ b/includes/omapip/isclib.h
@@ -3,7 +3,7 @@
connections to the isc and dns libraries */
/*
- * Copyright (c) 2009 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2009,2013 by Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -119,4 +119,6 @@ isclib_make_dst_key(char *inname,
isc_result_t dhcp_context_create(void);
void isclib_cleanup(void);
+void dhcp_signal_handler(int signal);
+
#endif /* ISCLIB_H */
diff --git a/omapip/dispatch.c b/omapip/dispatch.c
index e6aae453..dcef3248 100644
--- a/omapip/dispatch.c
+++ b/omapip/dispatch.c
@@ -3,7 +3,7 @@
I/O dispatcher. */
/*
- * Copyright (c) 2004,2007-2009 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004,2007-2009,2013 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1999-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
@@ -901,19 +901,65 @@ isc_result_t omapi_waiter_signal_handler (omapi_object_t *h,
return ISC_R_NOTFOUND;
}
+/** @brief calls a given function on every object
+ *
+ * @param func function to be called
+ * @param p parameter to be passed to each function instance
+ *
+ * @return result (ISC_R_SUCCESS if successful, error code otherwise)
+ */
isc_result_t omapi_io_state_foreach (isc_result_t (*func) (omapi_object_t *,
void *),
void *p)
{
- omapi_io_object_t *io;
+ omapi_io_object_t *io = NULL;
isc_result_t status;
+ omapi_io_object_t *next = NULL;
- for (io = omapi_io_states.next; io; io = io -> next) {
- if (io -> inner) {
- status = (*func) (io -> inner, p);
- if (status != ISC_R_SUCCESS)
- return status;
+ /*
+ * This just calls func on every inner object on the list. It would
+ * be much simpler in general case, but one of the operations could be
+ * release of the objects. Therefore we need to ref count the io and
+ * io->next pointers.
+ */
+
+ if (omapi_io_states.next) {
+ omapi_object_reference((omapi_object_t**)&io,
+ (omapi_object_t*)omapi_io_states.next,
+ MDL);
+ }
+
+ while(io) {
+ /* If there's a next object, save it */
+ if (io->next) {
+ omapi_object_reference((omapi_object_t**)&next,
+ (omapi_object_t*)io->next, MDL);
+ }
+ if (io->inner) {
+ status = (*func) (io->inner, p);
+ if (status != ISC_R_SUCCESS) {
+ /* Something went wrong. Let's stop using io & next pointer
+ * and bail out */
+ omapi_object_dereference((omapi_object_t**)&io, MDL);
+ if (next) {
+ omapi_object_dereference((omapi_object_t**)&next, MDL);
+ }
+ return status;
}
+ }
+ /* Update the io pointer and free the next pointer */
+ omapi_object_dereference((omapi_object_t**)&io, MDL);
+ if (next) {
+ omapi_object_reference((omapi_object_t**)&io,
+ (omapi_object_t*)next,
+ MDL);
+ omapi_object_dereference((omapi_object_t**)&next, MDL);
+ }
}
+
+ /*
+ * The only way to get here is when next is NULL. There's no need
+ * to dereference it.
+ */
return ISC_R_SUCCESS;
}
diff --git a/omapip/isclib.c b/omapip/isclib.c
index 1534dde5..5dcb12c0 100644
--- a/omapip/isclib.c
+++ b/omapip/isclib.c
@@ -1,5 +1,5 @@
/*
- * Copyright(c) 2009-2010 by Internet Systems Consortium, Inc.("ISC")
+ * Copyright(c) 2009-2010,2013 by Internet Systems Consortium, Inc.("ISC")
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -28,6 +28,7 @@
#include "dhcpd.h"
#include <sys/time.h>
+#include <signal.h>
dhcp_context_t dhcp_gbl_ctx;
@@ -217,3 +218,20 @@ isclib_make_dst_key(char *inname,
&b, dhcp_gbl_ctx.mctx, dstkey));
}
+/**
+ * signal handler that initiates server shutdown
+ *
+ * @param signal signal code that we received
+ */
+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);
+ }
+}
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
index 06a36d24..a218dece 100644
--- a/relay/dhcrelay.c
+++ b/relay/dhcrelay.c
@@ -34,6 +34,7 @@
#include "dhcpd.h"
#include <syslog.h>
+#include <signal.h>
#include <sys/time.h>
TIME default_lease_time = 43200; /* 12 hours... */
@@ -577,10 +578,13 @@ main(int argc, char **argv) {
dhcpv6_packet_handler = do_packet6;
#endif
+ /* install signal handlers */
+ signal(SIGINT, dhcp_signal_handler); /* control-c */
+ signal(SIGTERM, dhcp_signal_handler); /* kill */
+
/* Start dispatching packets and timeouts... */
dispatch();
- /* Not reached */
return (0);
}
diff --git a/server/dhcpd.c b/server/dhcpd.c
index e052301b..29d4f527 100644
--- a/server/dhcpd.c
+++ b/server/dhcpd.c
@@ -42,11 +42,11 @@ static const char url [] =
#include "dhcpd.h"
#include <omapip/omapip_p.h>
#include <syslog.h>
+#include <signal.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/time.h>
-#include <signal.h>
#if defined (PARANOIA)
# include <sys/types.h>
@@ -780,10 +780,20 @@ main(int argc, char **argv) {
omapi_set_int_value ((omapi_object_t *)dhcp_control_object,
(omapi_object_t *)0, "state", server_running);
- /* Receive packets and dispatch them... */
+ /* install signal handlers */
+ signal(SIGINT, dhcp_signal_handler); /* control-c */
+ signal(SIGTERM, dhcp_signal_handler); /* kill */
+
+ /*
+ * Receive packets and dispatch them...
+ * dispatch() will return only when we are shutting down.
+ */
dispatch ();
- /* Not reached */
+ log_info("Shutting down.");
+ dhcp_set_control_state(server_shutdown/*ignored*/, server_shutdown);
+
+ /* Let's return status code */
return 0;
}
#endif /* !UNIT_TEST */