]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
[master]
authorShawn Routhier <sar@isc.org>
Wed, 30 Oct 2013 20:52:36 +0000 (13:52 -0700)
committerShawn Routhier <sar@isc.org>
Wed, 30 Oct 2013 20:52:36 +0000 (13:52 -0700)
    [32692] Signal handlers added: sigint (ctrl-c) and sigterm (default kill)

RELNOTES
client/dhclient.c
common/dispatch.c
includes/omapip/isclib.h
omapip/dispatch.c
omapip/isclib.c
relay/dhcrelay.c
server/dhcpd.c

index 3e7350d5d2ab388ba2dc0b07fe15bb8e1b405c59..6c1ec67907e08b77acecf37fb6bab195f219c021 100644 (file)
--- 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
index c303f7e3add67f6e25084cf9920512fcc0e27104..f131e39302041b53a60e0e3e553ebc6acabafa61 100644 (file)
@@ -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;
 }
index 7c4434e716cfbacad5065bf36bf45d23235ce0dc..976d37e2b302874575fa622268663a0a254750a5 100644 (file)
@@ -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
index ddefeb5fcdf29c1487372f51d4d5f5e2f8e08695..7fd30feab280c359662381c4c72612389b3e89b5 100644 (file)
@@ -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 */
index e6aae45384477f77f9c4a2cae23e8abced92e139..dcef3248247f0e2370223251f5a89503c674c676 100644 (file)
@@ -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;
 }
index 1534dde52b36116479f0fbffce7e90866237aa4f..5dcb12c096c129fa662fd8a993440c91c102ffc9 100644 (file)
@@ -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);
+       }
+}
index 06a36d249b9ac2d433ba37a4a38f9f4a3fea34e2..a218decee16e8dfca561faff5ad771b1f63d0349 100644 (file)
@@ -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);
 }
 
index e052301ba85deda39c5eb4706975ac7b89f4a026..29d4f527dda0ecda4971c6ae11b62351cfd15d45 100644 (file)
@@ -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 */