terom@61: #define _GNU_SOURCE terom@61: #include terom@61: #include terom@61: #include terom@61: #include terom@61: terom@61: #include "signals.h" terom@61: #include "log.h" terom@61: terom@61: struct signals { terom@61: struct event_base *ev_base; terom@61: terom@61: struct signal { terom@61: struct event *ev; terom@61: } sig_list[MAX_SIGNALS]; terom@61: terom@61: int sig_count; terom@61: }; terom@61: terom@61: void signals_loopexit (int signal, short event, void *arg) { terom@61: struct signals *signals = arg; terom@61: terom@61: (void) event; terom@61: terom@61: INFO("[signal] caught %s: exiting the event loop", strsignal(signal)); terom@61: terom@61: if (event_base_loopexit(signals->ev_base, NULL)) terom@61: FATAL("event_base_loopexit"); terom@61: } terom@61: terom@61: void signals_ignore (int signal, short event, void *arg) { terom@61: struct signals *signals = arg; terom@61: terom@61: (void) signal; terom@61: (void) event; terom@61: (void) arg; terom@61: (void) signals; terom@61: terom@61: /* ignore */ terom@61: } terom@61: terom@61: struct signals *signals_alloc (struct event_base *ev_base) { terom@61: struct signals *signals = NULL; terom@61: terom@61: if ((signals = calloc(1, sizeof(*signals))) == NULL) terom@61: ERROR("calloc"); terom@61: terom@61: // simple attributes terom@61: signals->ev_base = ev_base; terom@61: terom@61: // done terom@61: return signals; terom@61: terom@61: error: terom@61: return NULL; terom@61: } terom@61: terom@61: int signals_add (struct signals *signals, int sigval, void (*sig_handler)(evutil_socket_t, short, void *)) { terom@61: struct signal *sig_info; terom@61: terom@61: // find our sig_info terom@61: assert(signals->sig_count < MAX_SIGNALS); terom@61: sig_info = &signals->sig_list[signals->sig_count++]; terom@61: terom@61: // set up the libevent signal events terom@61: if ((sig_info->ev = evsignal_new(signals->ev_base, sigval, sig_handler, signals)) == NULL) terom@61: PERROR("signal_new"); terom@61: terom@61: if (evsignal_add(sig_info->ev, NULL)) terom@61: PERROR("signal_add"); terom@61: terom@61: // success terom@61: return 0; terom@61: terom@61: error: terom@61: return -1; terom@61: } terom@61: terom@61: struct signals *signals_default (struct event_base *ev_base) { terom@61: struct signals *signals = NULL; terom@61: terom@61: // alloc signals terom@61: if ((signals = signals_alloc(ev_base)) == NULL) terom@61: return NULL; terom@61: terom@61: // add the set of default signals terom@61: if ( signals_add(signals, SIGPIPE, &signals_ignore) terom@61: || signals_add(signals, SIGINT, &signals_loopexit) terom@61: ) ERROR("signals_add"); terom@61: terom@61: // success terom@61: return signals; terom@61: terom@61: error: terom@61: if (signals) terom@61: signals_free(signals); terom@61: terom@61: return NULL; terom@61: } terom@61: terom@61: void signals_free (struct signals *signals) { terom@61: int i; terom@61: terom@61: // free all events terom@61: for (i = 0; i < signals->sig_count; i++) { terom@61: if (evsignal_del(signals->sig_list[i].ev)) terom@61: PWARNING("signal_del"); terom@61: terom@61: } terom@61: terom@61: // free the info itself terom@61: free(signals); terom@61: } terom@61: