]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Signal solution
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 27 Feb 2007 10:33:04 +0000 (10:33 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 27 Feb 2007 10:33:04 +0000 (10:33 +0000)
git-svn-id: file:///svn/unbound/trunk@152 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/daemon.c
daemon/daemon.h
daemon/worker.c
daemon/worker.h
doc/Changelog
util/netevent.c
util/random.c

index bb766c4ce73f3b558514738a9e5a5b5539167593..5c88a9f0b4e95567c28fd9cabfdab528524b9e49 100644 (file)
 #include "util/log.h"
 #include "util/config_file.h"
 #include "services/listen_dnsport.h"
-
-/* @@@ TODO remove */
-#include "pthread.h"
 #include <signal.h>
 
+/** How many quit requests happened. */
+static int sig_record_quit = 0;
+/** How many reload requests happened. */
+static int sig_record_reload = 0;
+
+/** used when no other sighandling happens, so we don't die
+  * when multiple signals in quick succession are sent to us. */
+static RETSIGTYPE record_sigh(int sig)
+{
+       switch(sig)
+       {
+               case SIGTERM:
+               case SIGQUIT:
+               case SIGINT:
+                       sig_record_quit++;
+                       break;
+               case SIGHUP:
+                       sig_record_reload++;
+                       break;
+               default:
+                       log_err("ignoring signal %d", sig);
+       }
+}
+
+/** 
+ * Signal handling during the time when netevent is disabled.
+ * Stores signals to replay later.
+ */
+static void
+signal_handling_record()
+{
+       if( signal(SIGTERM, record_sigh) == SIG_ERR ||
+               signal(SIGQUIT, record_sigh) == SIG_ERR ||
+               signal(SIGINT, record_sigh) == SIG_ERR ||
+               signal(SIGHUP, record_sigh) == SIG_ERR)
+               log_err("install sighandler: %s", strerror(errno));
+}
+
+/**
+ * Replay old signals.
+ * @param wrk: worker that handles signals.
+ */
+static void
+signal_handling_playback(struct worker* wrk)
+{
+       if(sig_record_quit)
+               worker_sighandler(SIGTERM, wrk);
+       if(sig_record_reload)
+               worker_sighandler(SIGHUP, wrk);
+       sig_record_quit = 0;
+       sig_record_reload = 0;
+}
+
 struct daemon* 
 daemon_init()
 {
@@ -60,6 +110,7 @@ daemon_init()
                sizeof(struct daemon));
        if(!daemon)
                return NULL;
+       signal_handling_record();
        lock_basic_init(&daemon->lock);
        daemon->need_to_exit = 0;
        return daemon;  
@@ -212,7 +263,7 @@ daemon_fork(struct daemon* daemon)
        if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports,
                BUFSZ, 1))
                fatal_exit("Could not initialize main thread");
-       /* see if other threads have started correctly? */
+       signal_handling_playback(daemon->workers[0]);
 
        /* Start resolver service on main thread. */
        log_info("start of service (%s).", PACKAGE_STRING);
@@ -231,6 +282,9 @@ daemon_cleanup(struct daemon* daemon)
 {
        int i;
        log_assert(daemon);
+       /* before stopping main worker, handle signals ourselves, so we
+          don't die on multiple reload signals for example. */
+       signal_handling_record();
        for(i=0; i<daemon->num; i++)
                worker_delete(daemon->workers[i]);
        free(daemon->workers);
index 0fb185d70543ee9d2cb4c27f9272720e05f21fff..46edecaa4dfef022b50786a2f20f0256c4516aab 100644 (file)
@@ -101,7 +101,8 @@ void daemon_fork(struct daemon* daemon);
 void daemon_cleanup(struct daemon* daemon);
 
 /**
- * Delete worker.
+ * Delete workers, close listening ports.
+ * @param daemon: the daemon.
  */
 void daemon_delete(struct daemon* daemon);
 
index e6da5a4832fc72412cf4e2cb70edb39038985cf2..c2f5eccdeedd0d5945f84332c228fde7f83d1d23 100644 (file)
@@ -376,15 +376,18 @@ worker_delete(struct worker* worker)
 {
        if(!worker) 
                return;
-       close(worker->cmd_send_fd);
+       if(worker->cmd_send_fd != -1)
+               close(worker->cmd_send_fd);
        worker->cmd_send_fd = -1;
-       close(worker->cmd_recv_fd);
+       if(worker->cmd_recv_fd != -1)
+               close(worker->cmd_recv_fd);
        worker->cmd_recv_fd = -1;
        listen_delete(worker->front);
        outside_network_delete(worker->back);
        comm_signal_delete(worker->comsig);
        comm_point_delete(worker->cmd_com);
        comm_base_delete(worker->base);
+       ub_randfree(worker->rndstate);
        free(worker->rndstate);
        free(worker);
 }
index ec01f5fd8fa22bdc0d985036f53c1770bd008b9b..72576a5f8556012f32f20caf53ae40d8ef66b67d 100644 (file)
@@ -157,4 +157,11 @@ int worker_set_fwd(struct worker* worker, const char* ip, int port);
 void worker_send_cmd(struct worker* worker, ldns_buffer* buffer,
         enum worker_commands cmd);
 
+/**
+ * Worker signal handler function. User argument is the worker itself.
+ * @param sig: signal number.
+ * @param arg: the worker (main worker) that handles signals.
+ */
+void worker_sighandler(int sig, void* arg);
+
 #endif /* DAEMON_WORKER_H */
index 36f7c0fdca66dc04cfeaa78fa11af16148777bd4..85ca5e211fcdf44d39e1eadb2d21e0f38cc5dcfa 100644 (file)
@@ -3,6 +3,8 @@
        - forking is used if no threading is available.
          Tested, it works, since pipes work across processes as well.
          Thread_join is replaced with waitpid. 
+       - During reloads the daemon will temporarily handle signals,
+         so that they do not result in problems.
 
 26 February 2007: Wouter
        - ub_random code used to select ID and port.
index a51d59217173a2916eba595090730076c795b493..28b6eecd0e38c508817fe5e52a9f35cd31086d50 100644 (file)
@@ -507,7 +507,8 @@ static void comm_point_local_handle_callback(int fd, short event, void* arg)
 
        if(event&EV_READ) {
                if(!comm_point_tcp_handle_read(fd, c, 1)) {
-                       log_err("error in localhdl");
+                       (void)(*c->callback)(c, c->cb_arg, NETEVENT_CLOSED, 
+                               NULL);
                }
                return;
        }
index 3e19da8767e5334b9858e289d692935f26727004..976b6a0e24527847f50a1d3629e8bb0ff6985edd 100644 (file)
@@ -357,5 +357,7 @@ ub_random (struct ub_randstate* s)
 
 void ub_randfree(struct ub_randstate* state)
 {
+       if(!state)
+               return;
        free(state->state);
 }