/* signal handling */ static int kq_sig_add(struct event_base *base, int nsignal, short old, short events, void *p) { struct kqop *kqop = base->evbase; struct kevent kev; struct timespec timeout = { 0, 0 }; (void)p; EVUTIL_ASSERT(nsignal >= 0 && nsignal < NSIG); memset(&kev, 0, sizeof(kev)); kev.ident = nsignal; kev.filter = EVFILT_SIGNAL; kev.flags = EV_ADD; /* Be ready for the signal if it is sent any * time between now and the next call to * kq_dispatch. */ if (kevent(kqop->kq, &kev, 1, NULL, 0, &timeout) == -1) return (-1); /* We can set the handler for most signals to SIG_IGN and * still have them reported to us in the queue. However, * if the handler for SIGCHLD is SIG_IGN, the system reaps * zombie processes for us, and we don't get any notification. * This appears to be the only signal with this quirk. */ if (evsig_set_handler_(base, nsignal, nsignal == SIGCHLD ? SIG_DFL : SIG_IGN) == -1) return (-1); return (0); }
static int evsig_add(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p) { struct evsig_info *sig = &base->sig; (void)p; EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG); /* catch signals if they happen quickly */ EVSIGBASE_LOCK(); if (evsig_base != base && evsig_base_n_signals_added) { event_warnx("Added a signal to event base %p with signals " "already added to event_base %p. Only one can have " "signals at a time with the %s backend. The base with " "the most recently added signal or the most recent " "event_base_loop() call gets preference; do " "not rely on this behavior in future Libevent versions.", base, evsig_base, base->evsel->name); } evsig_base = base; evsig_base_n_signals_added = ++sig->ev_n_signals_added; evsig_base_fd = base->sig.ev_signal_pair[1]; EVSIGBASE_UNLOCK(); event_debug(("%s: %d: changing signal handler", __func__, (int)evsignal)); if (evsig_set_handler_(base, (int)evsignal, evsig_handler) == -1) { goto err; } if (!sig->ev_signal_added) { if (event_add(&sig->ev_signal, NULL)) goto err; sig->ev_signal_added = 1; } return (0); err: EVSIGBASE_LOCK(); --evsig_base_n_signals_added; --sig->ev_n_signals_added; EVSIGBASE_UNLOCK(); return (-1); }