terom@48: #define _GNU_SOURCE terom@48: terom@48: #include "signals.h" terom@48: #include "log.h" terom@48: terom@48: #include terom@48: #include terom@48: #include terom@48: #include terom@48: terom@48: struct signals { terom@48: /** The libevent base to use */ terom@48: struct event_base *ev_base; terom@48: terom@48: /** Information about up to MAX_SIGNALS signals */ terom@48: struct signal { terom@48: /** The event we use to handle the signal */ terom@48: struct event *ev; terom@48: terom@48: } sig_list[MAX_SIGNALS]; terom@48: terom@48: /** Number of used sig_list slots */ terom@48: int sig_count; terom@48: }; terom@48: terom@48: void signals_loopexit (int signal, short event, void *arg) terom@48: { terom@48: struct signals *signals = arg; terom@48: terom@48: (void) event; terom@48: terom@48: log_info("caught %s: exiting", strsignal(signal)); terom@48: terom@48: if (event_base_loopexit(signals->ev_base, NULL)) terom@48: FATAL("event_base_loopexit"); terom@48: } terom@48: terom@48: void signals_ignore (int signal, short event, void *arg) terom@48: { terom@48: struct signals *signals = arg; terom@48: terom@48: (void) signal; terom@48: (void) event; terom@48: (void) arg; terom@48: (void) signals; terom@48: terom@48: /* ignore */ terom@48: } terom@48: terom@48: err_t signals_create (struct signals **signals_ptr, struct event_base *ev_base) terom@48: { terom@48: struct signals *signals; terom@48: terom@48: if ((signals = calloc(1, sizeof(*signals))) == NULL) terom@48: return ERR_CALLOC; terom@48: terom@48: // simple attributes terom@48: signals->ev_base = ev_base; terom@48: terom@48: // done terom@48: *signals_ptr = signals; terom@48: terom@48: return SUCCESS; terom@48: } terom@48: terom@48: err_t signals_add (struct signals *signals, int sigval, void (*sig_handler)(evutil_socket_t, short, void *), void *arg) terom@48: { terom@48: struct signal *sig_info; terom@48: terom@48: // find our sig_info terom@48: assert(signals->sig_count < MAX_SIGNALS); terom@48: sig_info = signals->sig_list + (signals->sig_count++); terom@48: terom@48: // set up the libevent signal events terom@48: if ((sig_info->ev = evsignal_new(signals->ev_base, sigval, sig_handler, arg)) == NULL) terom@48: return ERR_EVENT_NEW; terom@48: terom@48: if (evsignal_add(sig_info->ev, NULL)) terom@48: return ERR_EVENT_ADD; terom@48: terom@48: // ok terom@48: return SUCCESS; terom@48: } terom@48: terom@71: err_t signal_ignore (int signum, struct error_info *err) terom@71: { terom@71: struct sigaction act = { terom@71: .sa_handler = SIG_IGN, terom@71: }; terom@71: terom@71: // signall the handler terom@71: if (sigaction(signum, &act, NULL)) terom@71: RETURN_SET_ERROR_ERRNO(err, ERR_SIGACTION); terom@71: terom@71: // ok terom@71: return SUCCESS; terom@71: } terom@71: terom@48: struct signals *signals_default (struct event_base *ev_base) terom@48: { terom@48: struct signals *signals = NULL; terom@71: struct error_info err; terom@48: terom@48: // alloc signals terom@48: if (signals_create(&signals, ev_base)) terom@48: return NULL; terom@48: terom@48: // add the set of default signals terom@71: if (signal_ignore(SIGPIPE, &err)) terom@71: log_err_info(&err, "signal_ignore(SIGPIPE)"); terom@71: terom@71: if ((ERROR_CODE(&err) = signals_add(signals, SIGINT, &signals_loopexit, signals))) { terom@71: log_err_info(&err, "signals_add(SIGINT)"); terom@48: goto error; terom@71: } terom@71: terom@48: // ok terom@48: return signals; terom@48: terom@48: error: terom@71: signals_free(signals); terom@48: terom@48: return NULL; terom@48: } terom@48: terom@48: void signals_free (struct signals *signals) terom@48: { terom@48: int i; terom@48: terom@48: // free all events terom@48: for (i = 0; i < signals->sig_count; i++) { terom@109: event_free(signals->sig_list[i].ev); terom@48: } terom@48: terom@48: // free the info itself terom@48: free(signals); terom@48: } terom@48: