void evsig_process(struct event_base *base) { struct evsig_info *sig = &base->sig; sig_atomic_t ncalls; int i; base->sig.evsig_caught = 0; for (i = 1; i < NSIG; ++i) { ncalls = sig->evsigcaught[i]; if (ncalls == 0) continue; sig->evsigcaught[i] -= ncalls; evmap_signal_active(base, i, ncalls); } }
/* 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) { #ifdef _WIN32 n = recv(fd, signals, sizeof(signals), 0); #else n = read(fd, signals, sizeof(signals)); #endif 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) { ev_uint8_t sig = signals[i]; if (sig < NSIG) ncaught[sig]++; } } EVBASE_ACQUIRE_LOCK(base, th_base_lock); for (i = 0; i < NSIG; ++i) { if (ncaught[i]) evmap_signal_active(base, i, ncaught[i]); } EVBASE_RELEASE_LOCK(base, th_base_lock); }
/* 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];//NSIG在哪定义? struct event_base *base; base = arg; memset(&ncaught, 0, sizeof(ncaught)); while (1) { n = recv(fd, signals, sizeof(signals), 0); if (n == -1) { int err = evutil_socket_geterror(fd);//windows平台这是函数,而linux平台这是宏函数 if (! EVUTIL_ERR_RW_RETRIABLE(err)) //判断是否可重读写,即检查EINTR和EAGAIN event_sock_err(1, fd, "%s: recv", __func__); break; } else if (n == 0) { /* XXX warn? */ break; } for (i = 0; i < n; ++i) { ev_uint8_t sig = signals[i]; if (sig < NSIG) ncaught[sig]++;//记录传进来的信号 } } EVBASE_ACQUIRE_LOCK(base, th_base_lock);//base虽然是在本函数中定义的,貌似在栈上,但是他指向的地址是从外部传过来的,所以需要加锁 for (i = 0; i < NSIG; ++i) { if (ncaught[i]) evmap_signal_active(base, i, ncaught[i]);//激活base中等待的信号 } EVBASE_RELEASE_LOCK(base, th_base_lock); }
static int kq_dispatch(struct event_base *base, struct timeval *tv) { struct kqop *kqop = base->evbase; struct kevent *events = kqop->events; struct kevent *changes; struct timespec ts, *ts_p = NULL; int i, n_changes, res; if (tv != NULL) { TIMEVAL_TO_TIMESPEC(tv, &ts); ts_p = &ts; } /* Build "changes" from "base->changes" */ EVUTIL_ASSERT(kqop->changes); n_changes = kq_build_changes_list(&base->changelist, kqop); if (n_changes < 0) return -1; event_changelist_remove_all(&base->changelist, base); /* steal the changes array in case some broken code tries to call * dispatch twice at once. */ changes = kqop->changes; kqop->changes = NULL; /* Make sure that 'events' is at least as long as the list of changes: * otherwise errors in the changes can get reported as a -1 return * value from kevent() rather than as EV_ERROR events in the events * array. * * (We could instead handle -1 return values from kevent() by * retrying with a smaller changes array or a larger events array, * but this approach seems less risky for now.) */ if (kqop->events_size < n_changes) { int new_size = kqop->events_size; do { new_size *= 2; } while (new_size < n_changes); kq_grow_events(kqop, new_size); events = kqop->events; } EVBASE_RELEASE_LOCK(base, th_base_lock); res = kevent(kqop->kq, changes, n_changes, events, kqop->events_size, ts_p); EVBASE_ACQUIRE_LOCK(base, th_base_lock); EVUTIL_ASSERT(kqop->changes == NULL); kqop->changes = changes; if (res == -1) { if (errno != EINTR) { event_warn("kevent"); return (-1); } return (0); } event_debug(("%s: kevent reports %d", __func__, res)); for (i = 0; i < res; i++) { int which = 0; if (events[i].flags & EV_ERROR) { switch (events[i].data) { /* Can occur on delete if we are not currently * watching any events on this fd. That can * happen when the fd was closed and another * file was opened with that fd. */ case ENOENT: /* Can occur for reasons not fully understood * on FreeBSD. */ case EINVAL: continue; /* Can occur on a delete if the fd is closed. */ case EBADF: /* XXXX On NetBSD, we can also get EBADF if we * try to add the write side of a pipe, but * the read side has already been closed. * Other BSDs call this situation 'EPIPE'. It * would be good if we had a way to report * this situation. */ continue; /* These two can occur on an add if the fd was one side * of a pipe, and the other side was closed. */ case EPERM: case EPIPE: /* Report read events, if we're listening for * them, so that the user can learn about any * add errors. (If the operation was a * delete, then udata should be cleared.) */ if (events[i].udata) { /* The operation was an add: * report the error as a read. */ which |= EV_READ; break; } else { /* The operation was a del: * report nothing. */ continue; } /* Other errors shouldn't occur. */ default: errno = events[i].data; return (-1); } } else if (events[i].filter == EVFILT_READ) { which |= EV_READ; } else if (events[i].filter == EVFILT_WRITE) { which |= EV_WRITE; } else if (events[i].filter == EVFILT_SIGNAL) { which |= EV_SIGNAL; } if (!which) continue; if (events[i].filter == EVFILT_SIGNAL) { evmap_signal_active(base, events[i].ident, 1); } else { evmap_io_active(base, events[i].ident, which | EV_ET); } } if (res == kqop->events_size) { /* We used all the events space that we have. Maybe we should make it bigger. */ kq_grow_events(kqop, kqop->events_size * 2); } return (0); }
static int kq_dispatch(struct event_base *base, struct timeval *tv) { struct kqop *kqop = base->evbase; struct kevent *events = kqop->events; struct kevent *changes; struct timespec ts, *ts_p = NULL; int i, n_changes, res; if (tv != NULL) { TIMEVAL_TO_TIMESPEC(tv, &ts); ts_p = &ts; } /* Build "changes" from "base->changes" */ EVUTIL_ASSERT(kqop->changes); n_changes = kq_build_changes_list(&base->changelist, kqop); if (n_changes < 0) return -1; event_changelist_remove_all(&base->changelist, base); /* steal the changes array in case some broken code tries to call * dispatch twice at once. */ changes = kqop->changes; kqop->changes = NULL; EVBASE_RELEASE_LOCK(base, th_base_lock); res = kevent(kqop->kq, changes, n_changes, events, kqop->events_size, ts_p); EVBASE_ACQUIRE_LOCK(base, th_base_lock); EVUTIL_ASSERT(kqop->changes == NULL); kqop->changes = changes; if (res == -1) { if (errno != EINTR) { event_warn("kevent"); return (-1); } return (0); } event_debug(("%s: kevent reports %d", __func__, res)); for (i = 0; i < res; i++) { int which = 0; if (events[i].flags & EV_ERROR) { /* * Error messages that can happen, when a delete fails. * EBADF happens when the file descriptor has been * closed, * ENOENT when the file descriptor was closed and * then reopened. * EINVAL for some reasons not understood; EINVAL * should not be returned ever; but FreeBSD does :-\ * An error is also indicated when a callback deletes * an event we are still processing. In that case * the data field is set to ENOENT. */ if (events[i].data == EBADF || events[i].data == EINVAL || events[i].data == ENOENT) continue; errno = events[i].data; return (-1); } if (events[i].filter == EVFILT_READ) { which |= EV_READ; } else if (events[i].filter == EVFILT_WRITE) { which |= EV_WRITE; } else if (events[i].filter == EVFILT_SIGNAL) { which |= EV_SIGNAL; } if (!which) continue; if (events[i].filter == EVFILT_SIGNAL) { evmap_signal_active(base, events[i].ident, 1); } else { evmap_io_active(base, events[i].ident, which | EV_ET); } } if (res == kqop->events_size) { struct kevent *newresult; int size = kqop->events_size; /* We used all the events space that we have. Maybe we should make it bigger. */ size *= 2; newresult = mm_realloc(kqop->events, size * sizeof(struct kevent)); if (newresult) { kqop->events = newresult; kqop->events_size = size; } } return (0); }