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