libevent source code analysis of three --signal incident response

  Please indicate the source https://www.cnblogs.com/yang-zd/p/11365461.html  , thank you!

  libevent supports io event, timeout event, signal event, this file will analyze how libevent signal event is organized, and how to implement signal incident response.

1.  sigmap

Io similar event, event_base there is another hash table sigmap for storing signal events, hash tables using signal number array indexes, different events with a signal number to use doubly linked list (using a struct event structure ev_. Ev_signal. Ev_signal_next members to construct this list). Using the data structure struct event_signal_map with struct evmap_signal, defined as follows:

/* Used to map signal numbers to a list of events.  If EVMAP_USE_HT is not
   defined, this structure is also used as event_io_map, which maps fds to a
   list of events.
*/
struct event_signal_map {
    /* An array of evmap_io * or of evmap_signal *; empty entries are
     * set to NULL. */
    void **entries;
    /* The number of entries available in entries */
    int nentries;
};
/* An entry for an evmap_signal list: notes all the events that want to know
   when a signal triggers. */
struct evmap_signal {
    struct event_dlist events;
};

event_base that is a member sigmap example struct event_signal_map structure. entries pointer to a dynamically allocated array, the array length nentries is; is a member of an array pointer to dynamically allocated evmap_sinal structure. sigmap structure may be substantially represented in FIG. 1-1,

1-1 sigmap storage structure of FIG.

2. signal backend

  The back-end and back-end signal event io different events, their operation is not basically the same, libevent achieve signal event in the source file signal.c in back-end operations, and is used in event_base members struct eventop * evsigsel special event pointing signal the rear end of the operation, not multiplexing io evsel pointer pointing to the rear end, signal to backend information in struct evsig_info sig members.

  struct evsig_info defined below, here introduces ev_signal and ev_signal_pair [2] these two members.

/* Data structure for the default signal-handling implementation in signal.c
 */
struct evsig_info {
    /* Event watching ev_signal_pair[1] */
    struct event ev_signal;
    /* Socketpair used to send notifications from the signal handler */
    evutil_socket_t ev_signal_pair[2];
    /* True iff we've added the ev_signal event yet. */
    int ev_signal_added;
    /* Count of the number of signals we're currently watching. */
    int ev_n_signals_added;

    /* Array of previous signal handler objects before Libevent started
     * messing with them.  Used to restore old signal handlers. */
#ifdef EVENT__HAVE_SIGACTION
    struct sigaction **sh_old;
#else
    ev_sighandler_t **sh_old;
#endif
    /* Size of sh_old. */
    int sh_old_max;
};
  • ev_signal_pair [2] are two file descriptors, usually created with a pipe function.
  •   ev_signal is a full event (internal events), read event listener ev_signal_pair [0], which is added to event_base as a io event and the priority is set to 0, so that if the event occurs, it can callback It takes precedence.

  In the back-end signal, each event will be registered signal using sigaction function to modify the unified signal handler function static void __cdecl evsig_handler (int sig), this effect is a function of [1] write signal_number trigger to ev_signal_pair , activation events ev_signal. Function is defined as follows (delete the cross-platform code):

static void __cdecl
evsig_handler(int sig)
{
    int save_errno = errno;
    ev_uint8_t msg;

    if (evsig_base == NULL) {
        event_warnx(
            "%s: received signal %d, but have no base configured",
            __func__, sig);
        return;
    }

    /* Wake up our notification mechanism */
    msg = sig;
    {
        int r = write(evsig_base_fd, (char*)&msg, 1);
        (void)r; /* Suppress 'unused return value' and 'unused var' */
    }

    errno = save_errno;
}

  ev_signal callback function is defined in signal.c source files, static void evsig_cb (evutil_socket_t fd, short what, void * arg), its role is to be triggered from ev_signal_pair [0] read back the signal number, and sigmap All event on the corresponding signal_number added to the callback function to be executed in event_base. Function is defined as follows:

/* Callback for when the signal handler write a byte to our signaling socket */
static void
evsig_cb(evutil_socket_t fd, short what, void *arg)
{
    static char signals[1024];
    ev_ssize_t n;
    int i;
    int ncaught[NSIG];
    struct event_base *base;

    base = arg;
    memset(&ncaught, 0, sizeof(ncaught));

    while (1) {

        n = read(fd, signals, sizeof(signals));

        if (n == -1) {
            int err = evutil_socket_geterror(fd);
            if (! EVUTIL_ERR_RW_RETRIABLE(err))
                event_sock_err(1, fd, "%s: recv", __func__);
            break;
        } else if (n == 0) {
            /* XXX warn? */
            break;
        }
        for (i = 0; i < n; ++i) {
            SIG ev_uint8_t = Signals [I];
             IF (SIG < NSIG is) 
                ncaught [SIG] ++ ; 
        } 
    } 

    EVBASE_ACQUIRE_LOCK ( Base , th_base_lock);
     for (I = 0 ; I <NSIG is; ++ I) {
         IF (ncaught [I ]) 
            evmap_signal_active_ ( Base , I, ncaught [I]); // signal number i corresponding to the event to be added to the list to the callback 
    } 
    EVBASE_RELEASE_LOCK ( Base , th_base_lock); 
}

  When a signal occurs, evsig_handler write to ev_signal_pair [1] data (write singal number), activate ev_signal event, the callback function evsig_cb ev_signal events will read signal number is triggered from [0] on ev_signal_pair, then accordingly from event_base in the event all of sigmap corresponding callback function to be added to the callback list, the callback function will be performed in the event_base_loop completion signal in response to an event.

 

Guess you like

Origin www.cnblogs.com/yang-zd/p/11365461.html