src/spbot/signals.c
branchnew-lib-errors
changeset 217 7728d6ec3abf
parent 172 ea4972e51fa3
child 218 5229a5d098b2
equal deleted inserted replaced
216:a10ba529ae39 217:7728d6ec3abf
       
     1 
       
     2 #include "signals.h"
       
     3 #include "log.h"
       
     4 
       
     5 #define _GNU_SOURCE
       
     6 
       
     7 #include <string.h>
       
     8 #include <signal.h>
       
     9 #include <stdlib.h>
       
    10 #include <assert.h>
       
    11 
       
    12 struct signals {
       
    13     /** The libevent base to use */
       
    14     struct event_base *ev_base;
       
    15     
       
    16     /** Information about up to MAX_SIGNALS signals */
       
    17     struct signal {
       
    18         /** The event we use to handle the signal */
       
    19         struct event *ev;
       
    20 
       
    21     } sig_list[MAX_SIGNALS];
       
    22     
       
    23     /** Number of used sig_list slots */
       
    24     int sig_count;
       
    25 };
       
    26 
       
    27 void signals_loopexit (int signal, short event, void *arg) 
       
    28 {
       
    29     struct signals *signals = arg;
       
    30 
       
    31     (void) event;
       
    32 
       
    33     log_info("caught %s: exiting", /* strsignal(signal) */ "xxx");
       
    34     
       
    35     if (event_base_loopexit(signals->ev_base, NULL))
       
    36         FATAL("event_base_loopexit");
       
    37 }
       
    38 
       
    39 void signals_ignore (int signal, short event, void *arg)
       
    40 {
       
    41     struct signals *signals = arg;
       
    42     
       
    43     (void) signal;
       
    44     (void) event;
       
    45     (void) arg;
       
    46     (void) signals;
       
    47     
       
    48     /* ignore */
       
    49 }
       
    50 
       
    51 err_t signals_create (struct signals **signals_ptr, struct event_base *ev_base)
       
    52 {
       
    53     struct signals *signals;
       
    54 
       
    55     if ((signals = calloc(1, sizeof(*signals))) == NULL)
       
    56         return ERR_CALLOC;
       
    57     
       
    58     // simple attributes
       
    59     signals->ev_base = ev_base;
       
    60 
       
    61     // done
       
    62     *signals_ptr = signals;
       
    63 
       
    64     return SUCCESS;
       
    65 }
       
    66 
       
    67 err_t signals_add (struct signals *signals, int sigval, void (*sig_handler)(evutil_socket_t, short, void *), void *arg) 
       
    68 {
       
    69     struct signal *sig_info;
       
    70     
       
    71     // find our sig_info
       
    72     assert(signals->sig_count < MAX_SIGNALS);
       
    73     sig_info = signals->sig_list + (signals->sig_count++);
       
    74     
       
    75     // set up the libevent signal events
       
    76     if ((sig_info->ev = evsignal_new(signals->ev_base, sigval, sig_handler, arg)) == NULL)
       
    77         return ERR_EVENT_NEW;
       
    78 
       
    79     if (evsignal_add(sig_info->ev, NULL))
       
    80         return ERR_EVENT_ADD;
       
    81 
       
    82     // ok
       
    83     return SUCCESS;
       
    84 }
       
    85 
       
    86 err_t signal_ignore (int signum, struct error_info *err)
       
    87 {
       
    88     struct sigaction act = {
       
    89         .sa_handler     = SIG_IGN,
       
    90     };
       
    91     
       
    92     // signall the handler
       
    93     if (sigaction(signum, &act, NULL))
       
    94         RETURN_SET_ERROR_ERRNO(err, ERR_SIGACTION);
       
    95 
       
    96     // ok
       
    97     return SUCCESS;
       
    98 }
       
    99 
       
   100 struct signals *signals_default (struct event_base *ev_base) 
       
   101 {
       
   102     struct signals *signals = NULL;
       
   103     struct error_info err;
       
   104     
       
   105     // alloc signals
       
   106     if (signals_create(&signals, ev_base))
       
   107         return NULL;
       
   108     
       
   109     // add the set of default signals
       
   110     if (signal_ignore(SIGPIPE, &err))
       
   111         log_error(&err, "signal_ignore(SIGPIPE)");
       
   112 
       
   113     if ((ERROR_CODE(&err) = signals_add(signals, SIGINT, &signals_loopexit, signals))) {
       
   114         log_error(&err, "signals_add(SIGINT)");
       
   115         goto error;
       
   116     }
       
   117 
       
   118     // ok
       
   119     return signals;
       
   120 
       
   121 error:
       
   122     signals_free(signals);
       
   123 
       
   124     return NULL;
       
   125 }   
       
   126 
       
   127 void signals_free (struct signals *signals) 
       
   128 {
       
   129     int i;
       
   130     
       
   131     // free all events
       
   132     for (i = 0; i < signals->sig_count; i++) {
       
   133         event_free(signals->sig_list[i].ev);
       
   134     }
       
   135     
       
   136     // free the info itself
       
   137     free(signals);
       
   138 }
       
   139