mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-02-03 20:29:28 -05:00
signal handling.
git-svn-id: file:///svn/unbound/trunk@68 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
e1071511ab
commit
988be5cc7f
4 changed files with 188 additions and 10 deletions
|
|
@ -51,6 +51,7 @@
|
|||
#endif
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
/** timeout in seconds for UDP queries to auth servers. TODO: proper rtt */
|
||||
#define UDP_QUERY_TIMEOUT 5
|
||||
|
|
@ -169,6 +170,30 @@ static int worker_handle_request(struct comm_point* c, void* arg, int error,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/** worker signal callback */
|
||||
void worker_sighandler(int sig, void* arg)
|
||||
{
|
||||
/* note that log, print, syscalls here give race conditions. */
|
||||
struct worker* worker = (struct worker*)arg;
|
||||
switch(sig) {
|
||||
case SIGHUP:
|
||||
log_info("caught signal SIGHUP");
|
||||
comm_base_exit(worker->base);
|
||||
break;
|
||||
case SIGINT:
|
||||
log_info("caught signal SIGINT");
|
||||
comm_base_exit(worker->base);
|
||||
break;
|
||||
case SIGQUIT:
|
||||
log_info("caught signal SIGQUIT");
|
||||
comm_base_exit(worker->base);
|
||||
break;
|
||||
default:
|
||||
log_err("unknown signal: %d, ignored", sig);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct worker* worker_init(const char* port, int do_ip4, int do_ip6,
|
||||
int do_udp, int do_tcp, size_t buffer_size, size_t numports,
|
||||
int base_port)
|
||||
|
|
@ -180,27 +205,36 @@ struct worker* worker_init(const char* port, int do_ip4, int do_ip6,
|
|||
worker->base = comm_base_create();
|
||||
if(!worker->base) {
|
||||
log_err("could not create event handling base");
|
||||
worker_delete(worker);
|
||||
return NULL;
|
||||
}
|
||||
worker->comsig = comm_signal_create(worker->base, worker_sighandler,
|
||||
worker);
|
||||
if(!worker->comsig || !comm_signal_bind(worker->comsig, SIGHUP)
|
||||
|| !comm_signal_bind(worker->comsig, SIGINT)
|
||||
|| !comm_signal_bind(worker->comsig, SIGQUIT)) {
|
||||
log_err("could not create signal handlers");
|
||||
worker_delete(worker);
|
||||
return NULL;
|
||||
}
|
||||
worker->front = listen_create(worker->base, 0, NULL, port,
|
||||
do_ip4, do_ip6, do_udp, do_tcp, buffer_size,
|
||||
worker_handle_request, worker);
|
||||
if(!worker->front) {
|
||||
comm_base_delete(worker->base);
|
||||
worker_delete(worker);
|
||||
log_err("could not create listening sockets");
|
||||
return NULL;
|
||||
}
|
||||
worker->back = outside_network_create(worker->base,
|
||||
buffer_size, numports, NULL, 0, do_ip4, do_ip6, base_port);
|
||||
if(!worker->back) {
|
||||
comm_base_delete(worker->base);
|
||||
log_err("could not create outgoing sockets");
|
||||
return NULL;
|
||||
}
|
||||
/* init random(), large table size. */
|
||||
if(!initstate(time(NULL)^getpid(), worker->rndstate, RND_STATE_SIZE)) {
|
||||
log_err("could not init random numbers.");
|
||||
comm_base_delete(worker->base);
|
||||
worker_delete(worker);
|
||||
return NULL;
|
||||
}
|
||||
return worker;
|
||||
|
|
@ -217,6 +251,7 @@ void worker_delete(struct worker* worker)
|
|||
return;
|
||||
listen_delete(worker->front);
|
||||
outside_network_delete(worker->back);
|
||||
comm_signal_delete(worker->comsig);
|
||||
comm_base_delete(worker->base);
|
||||
free(worker);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,6 +79,9 @@ struct worker {
|
|||
|
||||
/** length of fwd_addr */
|
||||
socklen_t fwd_addrlen;
|
||||
|
||||
/** the signal handler */
|
||||
struct comm_signal *comsig;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
107
util/netevent.c
107
util/netevent.c
|
|
@ -75,6 +75,18 @@ struct internal_timer {
|
|||
uint8_t enabled;
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal signal structure, to store signal event in.
|
||||
*/
|
||||
struct internal_signal {
|
||||
/** libevent event type, alloced here */
|
||||
struct event ev;
|
||||
/** the commpoint it is part of */
|
||||
struct comm_signal* comm;
|
||||
/** next in signal list */
|
||||
struct internal_signal* next;
|
||||
};
|
||||
|
||||
/**
|
||||
* handle libevent callback for udp comm point.
|
||||
* @param fd: file descriptor.
|
||||
|
|
@ -107,10 +119,19 @@ static void comm_point_tcp_handle_callback(int fd, short event, void* arg);
|
|||
* @param fd: file descriptor (always -1).
|
||||
* @param event: event bits from libevent:
|
||||
* EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT.
|
||||
* @param arg: the comm_point structure.
|
||||
* @param arg: the comm_timer structure.
|
||||
*/
|
||||
static void comm_timer_callback(int fd, short event, void* arg);
|
||||
|
||||
/**
|
||||
* handle libevent callback for signal comm.
|
||||
* @param fd: file descriptor (used signal number).
|
||||
* @param event: event bits from libevent:
|
||||
* EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT.
|
||||
* @param arg: the internal commsignal structure.
|
||||
*/
|
||||
static void comm_signal_callback(int fd, short event, void* arg);
|
||||
|
||||
/** create a tcp handler with a parent */
|
||||
static struct comm_point* comm_point_create_tcp_handler(
|
||||
struct comm_base *base, struct comm_point* parent, size_t bufsize,
|
||||
|
|
@ -156,12 +177,17 @@ void
|
|||
comm_base_dispatch(struct comm_base* b)
|
||||
{
|
||||
int retval;
|
||||
while(1) {
|
||||
retval = event_base_dispatch(b->eb->base);
|
||||
if(retval != 0) {
|
||||
log_err("event_dispatch returned error %d, "
|
||||
"errno is %s", retval, strerror(errno));
|
||||
}
|
||||
retval = event_base_dispatch(b->eb->base);
|
||||
if(retval != 0) {
|
||||
fatal_exit("event_dispatch returned error %d, "
|
||||
"errno is %s", retval, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
void comm_base_exit(struct comm_base* b)
|
||||
{
|
||||
if(event_base_loopexit(b->eb->base, NULL) != 0) {
|
||||
log_err("Could not loopexit");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -500,3 +526,70 @@ comm_timer_is_set(struct comm_timer* timer)
|
|||
{
|
||||
return (int)timer->ev_timer->enabled;
|
||||
}
|
||||
|
||||
struct comm_signal* comm_signal_create(struct comm_base* base,
|
||||
void (*callback)(int, void*), void* cb_arg)
|
||||
{
|
||||
struct comm_signal* com = (struct comm_signal*)malloc(
|
||||
sizeof(struct comm_signal));
|
||||
if(!com) {
|
||||
log_err("malloc failed");
|
||||
return NULL;
|
||||
}
|
||||
com->base = base;
|
||||
com->callback = callback;
|
||||
com->cb_arg = cb_arg;
|
||||
com->ev_signal = NULL;
|
||||
return com;
|
||||
}
|
||||
|
||||
static void comm_signal_callback(int sig, short event, void* arg)
|
||||
{
|
||||
struct internal_signal* entry = (struct internal_signal*)arg;
|
||||
if(!(event & EV_SIGNAL))
|
||||
return;
|
||||
(*entry->comm->callback)(sig, entry->comm->cb_arg);
|
||||
}
|
||||
|
||||
int comm_signal_bind(struct comm_signal* comsig, int sig)
|
||||
{
|
||||
struct internal_signal* entry = (struct internal_signal*)calloc(1,
|
||||
sizeof(struct internal_signal));
|
||||
if(!entry) {
|
||||
log_err("malloc failed");
|
||||
return 0;
|
||||
}
|
||||
log_assert(comsig);
|
||||
entry->comm = comsig;
|
||||
/* add signal event */
|
||||
signal_set(&entry->ev, sig, comm_signal_callback, entry);
|
||||
if(event_base_set(comsig->base->eb->base, &entry->ev) != 0) {
|
||||
log_err("Could not set signal base");
|
||||
free(entry);
|
||||
return 0;
|
||||
}
|
||||
if(signal_add(&entry->ev, NULL) != 0) {
|
||||
log_err("Could not add signal handler");
|
||||
free(entry);
|
||||
return 0;
|
||||
}
|
||||
/* link into list */
|
||||
entry->next = comsig->ev_signal;
|
||||
comsig->ev_signal = entry;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void comm_signal_delete(struct comm_signal* comsig)
|
||||
{
|
||||
struct internal_signal* p, *np;
|
||||
if(!comsig)
|
||||
return;
|
||||
p=comsig->ev_signal;
|
||||
while(p) {
|
||||
np = p->next;
|
||||
signal_del(&p->ev);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
free(comsig);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -199,6 +199,23 @@ struct comm_timer {
|
|||
void* cb_arg;
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure only for signal events.
|
||||
*/
|
||||
struct comm_signal {
|
||||
/** the communication base */
|
||||
struct comm_base* base;
|
||||
|
||||
/** the internal event stuff */
|
||||
struct internal_signal* ev_signal;
|
||||
|
||||
/** callback function, takes signal number and user arg */
|
||||
void (*callback)(int, void*);
|
||||
|
||||
/** callback user argument */
|
||||
void* cb_arg;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new comm base.
|
||||
* @return: the new comm base. NULL on error.
|
||||
|
|
@ -218,6 +235,12 @@ void comm_base_delete(struct comm_base* b);
|
|||
*/
|
||||
void comm_base_dispatch(struct comm_base* b);
|
||||
|
||||
/**
|
||||
* Exit from dispatch loop.
|
||||
* @param b: the communicatio base that is in dispatch().
|
||||
*/
|
||||
void comm_base_exit(struct comm_base* b);
|
||||
|
||||
/**
|
||||
* Create an UDP comm point. Calls malloc.
|
||||
* setups the structure with the parameters you provide.
|
||||
|
|
@ -327,4 +350,28 @@ void comm_timer_delete(struct comm_timer* timer);
|
|||
*/
|
||||
int comm_timer_is_set(struct comm_timer* timer);
|
||||
|
||||
/**
|
||||
* Create a signal handler.
|
||||
* @param base: communication base to use.
|
||||
* @param callback: called when signal is caught.
|
||||
* @param cb_arg: user argument to callback
|
||||
* @return: the signal struct (bind it to a signal) or NULL on error.
|
||||
*/
|
||||
struct comm_signal* comm_signal_create(struct comm_base* base,
|
||||
void (*callback)(int, void*), void* cb_arg);
|
||||
|
||||
/**
|
||||
* Bind signal struct to catch a signal.
|
||||
* @param comsig: the communication point, with callback information.
|
||||
* @param sig: signal number.
|
||||
* @return: true on success. false on error.
|
||||
*/
|
||||
int comm_signal_bind(struct comm_signal* comsig, int sig);
|
||||
|
||||
/**
|
||||
* Delete the signal communication point.
|
||||
* @param comsig: to delete.
|
||||
*/
|
||||
void comm_signal_delete(struct comm_signal* comsig);
|
||||
|
||||
#endif /* NET_EVENT_H */
|
||||
|
|
|
|||
Loading…
Reference in a new issue