signal handling.

git-svn-id: file:///svn/unbound/trunk@68 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-02-05 16:46:40 +00:00
parent e1071511ab
commit 988be5cc7f
4 changed files with 188 additions and 10 deletions

View file

@ -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);
}

View file

@ -79,6 +79,9 @@ struct worker {
/** length of fwd_addr */
socklen_t fwd_addrlen;
/** the signal handler */
struct comm_signal *comsig;
};
/**

View file

@ -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);
}

View file

@ -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 */