int evsig_init_(struct event_base *base) { /* * Our signal handler is going to write to one end of the socket * pair to wake up our event loop. The event loop then scans for * signals that got delivered. */ if (evutil_make_internal_pipe_(base->sig.ev_signal_pair) == -1) { #ifdef _WIN32 /* Make this nonfatal on win32, where sometimes people have localhost firewalled. */ event_sock_warn(-1, "%s: socketpair", __func__); #else event_sock_err(1, -1, "%s: socketpair", __func__); #endif return -1; } if (base->sig.sh_old) { mm_free(base->sig.sh_old); } base->sig.sh_old = NULL; base->sig.sh_old_max = 0; event_assign(&base->sig.ev_signal, base, base->sig.ev_signal_pair[0], EV_READ | EV_PERSIST, evsig_cb, base); base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL; event_priority_set(&base->sig.ev_signal, 0); base->evsigsel = &evsigops; return 0; }
static void sock_err_fn(void) { evutil_socket_t fd = socket(AF_INET, SOCK_STREAM, 0); #ifdef _WIN32 EVUTIL_SET_SOCKET_ERROR(WSAEWOULDBLOCK); #else errno = EAGAIN; #endif event_sock_err(20, fd, "Unhappy socket"); }
/* 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[1]; ev_ssize_t n; (void)arg; /* Suppress "unused variable" warning. */ n = recv(fd, signals, sizeof(signals), 0); if (n == -1) event_sock_err(1, fd, "%s: read", __func__); }
/* 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); }
int evsig_init(struct event_base *base) { /* * Our signal handler is going to write to one end of the socket * pair to wake up our event loop. The event loop then scans for * signals that got delivered. */ if (evutil_socketpair( AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1) { #ifdef WIN32 /* Make this nonfatal on win32, where sometimes people have localhost firewalled. */ event_sock_warn(-1, "%s: socketpair", __func__); #else event_sock_err(1, -1, "%s: socketpair", __func__); #endif return -1; } evutil_make_socket_closeonexec(base->sig.ev_signal_pair[0]); evutil_make_socket_closeonexec(base->sig.ev_signal_pair[1]); base->sig.sh_old = NULL; base->sig.sh_old_max = 0; base->sig.evsig_caught = 0; memset(&base->sig.evsigcaught, 0, sizeof(sig_atomic_t)*NSIG); evutil_make_socket_nonblocking(base->sig.ev_signal_pair[0]); event_assign(&base->sig.ev_signal, base, base->sig.ev_signal_pair[1], EV_READ | EV_PERSIST, evsig_cb, &base->sig.ev_signal); base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL; base->evsigsel = &evsigops; base->evsigbase = &base->sig; return 0; }
//初始化base->sig成员 int evsig_init(struct event_base *base) { /* * Our signal handler is going to write to one end of the socket * pair to wake up our event loop. The event loop then scans for * signals that got delivered. //这感觉就是上一个函数的功能 */ if (evutil_socketpair( AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1) { #ifdef WIN32 /* Make this nonfatal on win32, where sometimes people have localhost firewalled. */ event_sock_warn(-1, "%s: socketpair", __func__); #else event_sock_err(1, -1, "%s: socketpair", __func__); #endif return -1; } evutil_make_socket_closeonexec(base->sig.ev_signal_pair[0]);//两个都设置执行时关闭 evutil_make_socket_closeonexec(base->sig.ev_signal_pair[1]); base->sig.sh_old = NULL; //? base->sig.sh_old_max = 0; evutil_make_socket_nonblocking(base->sig.ev_signal_pair[0]);//设置为非阻塞 evutil_make_socket_nonblocking(base->sig.ev_signal_pair[1]); event_assign(&base->sig.ev_signal, base, base->sig.ev_signal_pair[1],//注册了上一个函数evsig_cb为回调函数 EV_READ | EV_PERSIST, evsig_cb, base); base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL;//sig为evsig_info类型,ev_signal为event类型。设置为内部,一直没搞懂是啥 event_priority_set(&base->sig.ev_signal, 0);//初始优先级为0 base->evsigsel = &evsigops;//设置信号处理的后端 return 0; }
/* 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 void test_evutil_log(void *ptr) { evutil_socket_t fd = -1; char buf[128]; event_set_log_callback(logfn); event_set_fatal_callback(fatalfn); #define RESET() do { \ logsev = exited = exitcode = 0; \ if (logmsg) free(logmsg); \ logmsg = NULL; \ } while (0) #define LOGEQ(sev,msg) do { \ tt_int_op(logsev,==,sev); \ tt_assert(logmsg != NULL); \ tt_str_op(logmsg,==,msg); \ } while (0) event_errx(2, "Fatal error; too many kumquats (%d)", 5); LOGEQ(_EVENT_LOG_ERR, "Fatal error; too many kumquats (5)"); tt_int_op(exitcode,==,2); RESET(); event_warnx("Far too many %s (%d)", "wombats", 99); LOGEQ(_EVENT_LOG_WARN, "Far too many wombats (99)"); tt_int_op(exited,==,0); RESET(); event_msgx("Connecting lime to coconut"); LOGEQ(_EVENT_LOG_MSG, "Connecting lime to coconut"); tt_int_op(exited,==,0); RESET(); event_debug(("A millisecond passed! We should log that!")); #ifdef USE_DEBUG LOGEQ(_EVENT_LOG_DEBUG, "A millisecond passed! We should log that!"); #else tt_int_op(logsev,==,0); tt_ptr_op(logmsg,==,NULL); #endif RESET(); /* Try with an errno. */ errno = ENOENT; event_warn("Couldn't open %s", "/bad/file"); evutil_snprintf(buf, sizeof(buf), "Couldn't open /bad/file: %s",strerror(ENOENT)); LOGEQ(_EVENT_LOG_WARN,buf); tt_int_op(exited, ==, 0); RESET(); errno = ENOENT; event_err(5,"Couldn't open %s", "/very/bad/file"); evutil_snprintf(buf, sizeof(buf), "Couldn't open /very/bad/file: %s",strerror(ENOENT)); LOGEQ(_EVENT_LOG_ERR,buf); tt_int_op(exitcode, ==, 5); RESET(); /* Try with a socket errno. */ fd = socket(AF_INET, SOCK_STREAM, 0); #ifdef WIN32 evutil_snprintf(buf, sizeof(buf), "Unhappy socket: %s", evutil_socket_error_to_string(WSAEWOULDBLOCK)); EVUTIL_SET_SOCKET_ERROR(WSAEWOULDBLOCK); #else evutil_snprintf(buf, sizeof(buf), "Unhappy socket: %s", strerror(EAGAIN)); errno = EAGAIN; #endif event_sock_warn(fd, "Unhappy socket"); LOGEQ(_EVENT_LOG_WARN, buf); tt_int_op(exited,==,0); RESET(); #ifdef WIN32 EVUTIL_SET_SOCKET_ERROR(WSAEWOULDBLOCK); #else errno = EAGAIN; #endif event_sock_err(200, fd, "Unhappy socket"); LOGEQ(_EVENT_LOG_ERR, buf); tt_int_op(exitcode,==,200); RESET(); #undef RESET #undef LOGEQ end: if (logmsg) free(logmsg); if (fd >= 0) EVUTIL_CLOSESOCKET(fd); }