Mercurial > hg > dhcpcd
changeset 5301:e6f1372f2cf0 draft
eloop: Just use ppoll(2)
epoll and kqueue are really too heavy weight.
With privsep, we now favour more processes for BPF and per address sockets.
As such, the number of fds to monitor will always be quite small.
All modern OS now have ppoll(2) (NetBSD has pollts, which is the same)
which works perfectly for us.
If neither are present, the a wrapper around pselect(2) is provided,
which can be found on all POSIX systems.
This makes the code a lot smaller and easier to follow.
The reduced binary size and memory usage is a nice win here.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Wed, 03 Jun 2020 23:30:08 +0100 |
| parents | d6366bcea63f |
| children | ef799c0ff5cb |
| files | BUILDING.md configure src/dhcpcd.c src/eloop.c src/eloop.h src/privsep-root.c src/privsep.c |
| diffstat | 7 files changed, 121 insertions(+), 563 deletions(-) [+] |
line wrap: on
line diff
--- a/BUILDING.md Wed Jun 03 23:12:59 2020 +0100 +++ b/BUILDING.md Wed Jun 03 23:30:08 2020 +0100 @@ -129,18 +129,6 @@ NOTE: in Gentoo at least, `sys-fs/udev` as provided by systemd leaks memory `sys-fs/eudev`, the fork of udev does not and as such is recommended. -## select -dhcpcd uses eloop.c, which is a portable main event loop with timeouts and -signal handling. Unlike libevent and similar, it can be transplanted directly -within the application - the only caveat outside of POSIX calls is that -you provide queue.h based on a recent BSD (glibc sys/queue.h is not enough). -eloop supports the following polling mechanisms, listed in order of preference: - kqueue, epoll, pollts, ppoll and pselect. -If signal handling is disabled (ie in RTEMS or other single process -OS's) then eloop can use poll. -You can decide which polling mechanism dhcpcd will select in eloop like so -`./configure --with-poll=[kqueue|epoll|pselect|pollts|ppoll]` - ## Importing into another source control system To import the full sources, use the import target. @@ -153,8 +141,7 @@ ## Hooks Not all the hooks in dhcpcd-hooks are installed by default. -By default we install `01-test`, `02-dump`, `10-mtu`, `20-resolv.conf` -and `30-hostname`. +By default we install `01-test`, `20-resolv.conf`and `30-hostname`. The other hooks, `10-wpa_supplicant`, `15-timezone` and `29-lookup-hostname` are installed to `$(datadir)/dhcpcd/hooks` by default and need to be copied to `$(libexecdir)/dhcpcd-hooks` for use.
--- a/configure Wed Jun 03 23:12:59 2020 +0100 +++ b/configure Wed Jun 03 23:30:08 2020 +0100 @@ -1211,65 +1211,42 @@ echo "#define HAVE_REALLOCARRAY" >>$CONFIG_H if [ -z "$POLL" ]; then - printf "Testing for kqueue1 ... " - cat <<EOF >_kqueue.c -#include <sys/types.h> -#include <sys/event.h> + printf "Testing for ppoll ... " + cat <<EOF >_ppoll.c +#include <poll.h> +#include <stddef.h> int main(void) { - return kqueue1(0); -} -EOF - if $XCC _kqueue.c -o _kqueue 2>&3; then - POLL=kqueue1 - echo "yes" - else - echo "no" - fi - rm -f _kqueue.c _kqueue -fi -if [ -z "$POLL" ]; then - printf "Testing for kqueue ... " - cat <<EOF >_kqueue.c -#include <sys/types.h> -#include <sys/event.h> -int main(void) { - return kqueue(); + struct pollfd fds; + return ppoll(&fds, 1, NULL, NULL); } EOF - if $XCC _kqueue.c -o _kqueue 2>&3; then - POLL=kqueue - echo "yes" - else - echo "no" - fi - rm -f _kqueue.c _kqueue -fi -if [ -z "$POLL" ]; then - printf "Testing for epoll ... " - cat <<EOF >_epoll.c -#ifdef __linux__ -#include <linux/version.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) -#error kernel has buggy epoll_wait timeout -#endif -#endif - -#include <sys/epoll.h> -#include <unistd.h> -int main(void) { - epoll_create1(EPOLL_CLOEXEC); - epoll_pwait(-1, NULL, 0, 0, NULL); - return 0; -} -EOF - if $XCC _epoll.c -o _epoll 2>&3; then - POLL=epoll - echo "#define HAVE_EPOLL" >>$CONFIG_MK + if $XCC _ppoll.c -o _ppoll 2>&3; then + POLL=ppoll + echo "#define HAVE_PPOLL" >>$CONFIG_MK echo "yes" else echo "no" fi - rm -f _epoll.c _epoll + rm -f _ppoll.c _ppoll +fi +if [ -z "$POLL" ]; then + printf "Testing for pollts ... " + cat <<EOF >_pollts.c +#include <poll.h> +#include <stddef.h> +int main(void) { + struct pollfd fds; + return pollts(&fds, 1, NULL, NULL); +} +EOF + if $XCC _pollts.c -o _pollts 2>&3; then + POLL=pollts + echo "#define HAVE_PPOLL" >>$CONFIG_MK + echo "yes" + else + echo "no" + fi + rm -f _pollts.c _pollts fi if [ -z "$POLL" ]; then printf "Testing for pselect ... " @@ -1290,22 +1267,12 @@ rm -f _pselect.c _pselect fi case "$POLL" in -kqueue1) - echo "#define HAVE_KQUEUE" >>$CONFIG_H - echo "#define HAVE_KQUEUE1" >>$CONFIG_H - ;; -kqueue) - echo "#define HAVE_KQUEUE" >>$CONFIG_H - ;; -epoll) - echo "#define HAVE_EPOLL" >>$CONFIG_H +ppoll) + echo "#define HAVE_PPOLL" >>$CONFIG_H ;; pollts) echo "#define HAVE_POLLTS" >>$CONFIG_H ;; -ppoll) - echo "#define HAVE_PPOLL" >>$CONFIG_H - ;; pselect) echo "#define HAVE_PSELECT" >>$CONFIG_H ;;
--- a/src/dhcpcd.c Wed Jun 03 23:12:59 2020 +0100 +++ b/src/dhcpcd.c Wed Jun 03 23:30:08 2020 +0100 @@ -2039,13 +2039,9 @@ signal(dhcpcd_signals_ignore[si], SIG_IGN); /* Save signal mask, block and redirect signals to our handler */ - if (eloop_signal_set_cb(ctx.eloop, + eloop_signal_set_cb(ctx.eloop, dhcpcd_signals, dhcpcd_signals_len, - dhcpcd_signal_cb, &ctx) == -1) - { - logerr("%s: eloop_signal_set_cb", __func__); - goto exit_failure; - } + dhcpcd_signal_cb, &ctx); if (eloop_signal_mask(ctx.eloop, &ctx.sigset) == -1) { logerr("%s: eloop_signal_mask", __func__); goto exit_failure; @@ -2211,7 +2207,6 @@ logerr("fork"); goto exit_failure; case 0: - eloop_requeue(ctx.eloop); break; default: ctx.options |= DHCPCD_FORKED; /* A lie */
--- a/src/eloop.c Wed Jun 03 23:12:59 2020 +0100 +++ b/src/eloop.c Wed Jun 03 23:30:08 2020 +0100 @@ -26,60 +26,30 @@ * SUCH DAMAGE. */ -#if (defined(__unix__) || defined(unix)) && !defined(USG) -#include <sys/param.h> -#endif #include <sys/time.h> #include <assert.h> #include <errno.h> #include <limits.h> +#include <poll.h> #include <signal.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -/* config.h should define HAVE_KQUEUE, HAVE_EPOLL, etc. */ +/* config.h should define HAVE_PPOLL, etc. */ #if defined(HAVE_CONFIG_H) && !defined(NO_CONFIG_H) #include "config.h" #endif -/* Attempt to autodetect kqueue or epoll. - * Failing that, fall back to pselect. */ -#if !defined(HAVE_KQUEUE) && !defined(HAVE_EPOLL) && !defined(HAVE_PSELECT) && \ - !defined(HAVE_POLLTS) && !defined(HAVE_PPOLL) -#if defined(BSD) -/* Assume BSD has a working sys/queue.h and kqueue(2) interface. */ -#define HAVE_SYS_QUEUE_H -#define HAVE_KQUEUE -#define WARN_SELECT -#elif defined(__linux__) || defined(__sun) -/* Assume Linux and Solaris have a working epoll(3) interface. */ -#define HAVE_EPOLL -#define WARN_SELECT -#else -/* pselect(2) is a POSIX standard. */ +#if defined(HAVE_PPOLL) +#elif defined(HAVE_POLLTS) +#define ppoll pollts +#elif !defined(HAVE_PSELECT) +#pragma message("Compiling eloop with pselect(2) support.") #define HAVE_PSELECT -#define WARN_SELECT -#endif -#endif - -/* pollts and ppoll require poll. - * pselect is wrapped in a pollts/ppoll style interface - * and as such require poll as well. */ -#if defined(HAVE_PSELECT) || defined(HAVE_POLLTS) || defined(HAVE_PPOLL) -#ifndef HAVE_POLL -#define HAVE_POLL -#endif -#if defined(HAVE_POLLTS) -#define POLLTS pollts -#elif defined(HAVE_PPOLL) -#define POLLTS ppoll -#else -#define POLLTS eloop_pollts -#define ELOOP_NEED_POLLTS -#endif +#define ppoll eloop_ppoll #endif #include "eloop.h" @@ -95,42 +65,9 @@ #endif #endif -#if defined(HAVE_KQUEUE) -#include <sys/event.h> -#include <fcntl.h> -#ifdef __NetBSD__ -/* udata is void * except on NetBSD. - * lengths are int except on NetBSD. */ -#define UPTR(x) ((intptr_t)(x)) -#define LENC(x) (x) -#else -#define UPTR(x) (x) -#define LENC(x) ((int)(x)) -#endif -#elif defined(HAVE_EPOLL) -#include <sys/epoll.h> -#elif defined(HAVE_POLL) -#if defined(HAVE_PSELECT) +#ifdef HAVE_PSELECT #include <sys/select.h> #endif -#include <poll.h> -#endif - -#ifdef WARN_SELECT -#if defined(HAVE_KQUEUE) -#pragma message("Compiling eloop with kqueue(2) support.") -#elif defined(HAVE_EPOLL) -#pragma message("Compiling eloop with epoll(7) support.") -#elif defined(HAVE_PSELECT) -#pragma message("Compiling eloop with pselect(2) support.") -#elif defined(HAVE_PPOLL) -#pragma message("Compiling eloop with ppoll(2) support.") -#elif defined(HAVE_POLLTS) -#pragma message("Compiling eloop with pollts(2) support.") -#else -#error Unknown select mechanism for eloop -#endif -#endif /* Our structures require TAILQ macros, which really every libc should * ship as they are useful beyond belief. @@ -171,6 +108,7 @@ void *read_cb_arg; void (*write_cb)(void *); void *write_cb_arg; + struct pollfd *pollfd; }; struct eloop_timeout { @@ -183,11 +121,9 @@ }; struct eloop { - size_t events_len; TAILQ_HEAD (event_head, eloop_event) events; + size_t nevents; struct event_head free_events; - int events_maxfd; - struct eloop_event **event_fds; struct timespec now; TAILQ_HEAD (timeout_head, eloop_timeout) timeouts; @@ -200,12 +136,8 @@ void (*signal_cb)(int, void *); void *signal_cb_ctx; -#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) - int poll_fd; -#elif defined(HAVE_POLL) struct pollfd *fds; - size_t fds_len; -#endif + size_t nfds; int exitnow; int exitcode; @@ -229,30 +161,10 @@ } #endif -#ifdef HAVE_POLL -static void -eloop_event_setup_fds(struct eloop *eloop) -{ - struct eloop_event *e; - size_t i; - - i = 0; - TAILQ_FOREACH(e, &eloop->events, next) { - eloop->fds[i].fd = e->fd; - eloop->fds[i].events = 0; - if (e->read_cb) - eloop->fds[i].events |= POLLIN; - if (e->write_cb) - eloop->fds[i].events |= POLLOUT; - eloop->fds[i].revents = 0; - i++; - } -} - -#ifdef ELOOP_NEED_POLLTS -/* Wrapper around pselect, to imitate the NetBSD pollts call. */ +#ifdef HAVE_PSELECT +/* Wrapper around pselect, to imitate the ppoll call. */ static int -eloop_pollts(struct pollfd * fds, nfds_t nfds, +eloop_ppoll(struct pollfd * fds, nfds_t nfds, const struct timespec *ts, const sigset_t *sigmask) { fd_set read_fds, write_fds; @@ -287,10 +199,7 @@ return r; } -#endif /* pollts */ -#else /* !HAVE_POLL */ -#define eloop_event_setup_fds(a) {} -#endif /* HAVE_POLL */ +#endif unsigned long long eloop_timespec_diff(const struct timespec *tsp, const struct timespec *usp, @@ -360,19 +269,33 @@ eloop->now = now; } +static void +eloop_event_setup_fds(struct eloop *eloop) +{ + struct eloop_event *e; + struct pollfd *pfd; + + pfd = eloop->fds; + TAILQ_FOREACH(e, &eloop->events, next) { + e->pollfd = pfd; + pfd->fd = e->fd; + pfd->events = 0; + if (e->read_cb != NULL) + pfd->events |= POLLIN; + if (e->write_cb != NULL) + pfd->events |= POLLOUT; + pfd->revents = 0; + pfd++; + } +} + int eloop_event_add_rw(struct eloop *eloop, int fd, void (*read_cb)(void *), void *read_cb_arg, void (*write_cb)(void *), void *write_cb_arg) { struct eloop_event *e; -#if defined(HAVE_KQUEUE) - struct kevent ke[2]; -#elif defined(HAVE_EPOLL) - struct epoll_event epe; -#elif defined(HAVE_POLL) - struct pollfd *nfds; -#endif + struct pollfd *pfd; assert(eloop != NULL); assert(read_cb != NULL || write_cb != NULL); @@ -381,122 +304,41 @@ return -1; } -#ifdef HAVE_EPOLL - memset(&epe, 0, sizeof(epe)); - epe.data.fd = fd; - epe.events = EPOLLIN; - if (write_cb) - epe.events |= EPOLLOUT; -#endif - - /* We should only have one callback monitoring the fd. */ - if (fd <= eloop->events_maxfd) { - if ((e = eloop->event_fds[fd]) != NULL) { - int error; - -#if defined(HAVE_KQUEUE) - EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ, EV_ADD, - 0, 0, UPTR(e)); - if (write_cb) - EV_SET(&ke[1], (uintptr_t)fd, EVFILT_WRITE, - EV_ADD, 0, 0, UPTR(e)); - else if (e->write_cb) - EV_SET(&ke[1], (uintptr_t)fd, EVFILT_WRITE, - EV_DELETE, 0, 0, UPTR(e)); - error = kevent(eloop->poll_fd, ke, - e->write_cb || write_cb ? 2 : 1, NULL, 0, NULL); -#elif defined(HAVE_EPOLL) - epe.data.ptr = e; - error = epoll_ctl(eloop->poll_fd, EPOLL_CTL_MOD, - fd, &epe); -#else - error = 0; -#endif - if (read_cb) { - e->read_cb = read_cb; - e->read_cb_arg = read_cb_arg; - } - if (write_cb) { - e->write_cb = write_cb; - e->write_cb_arg = write_cb_arg; - } - eloop_event_setup_fds(eloop); - return error; - } - } else { - struct eloop_event **new_fds; - int maxfd, i; - - /* Reserve ourself and 4 more. */ - maxfd = fd + 4; - new_fds = eloop_realloca(eloop->event_fds, - ((size_t)maxfd + 1), sizeof(*eloop->event_fds)); - if (new_fds == NULL) - return -1; - - /* set new entries NULL as the fd's may not be contiguous. */ - for (i = maxfd; i > eloop->events_maxfd; i--) - new_fds[i] = NULL; - - eloop->event_fds = new_fds; - eloop->events_maxfd = maxfd; + TAILQ_FOREACH(e, &eloop->events, next) { + if (e->fd == fd) + break; } - /* Allocate a new event if no free ones already allocated. */ - if ((e = TAILQ_FIRST(&eloop->free_events))) { - TAILQ_REMOVE(&eloop->free_events, e, next); - } else { - e = malloc(sizeof(*e)); - if (e == NULL) - goto err; + if (e == NULL) { + if (eloop->nevents + 1 > eloop->nfds) { + pfd = eloop_realloca(eloop->fds, eloop->nevents + 1, + sizeof(*pfd)); + if (pfd == NULL) + return -1; + eloop->fds = pfd; + eloop->nfds++; + } + + e = TAILQ_FIRST(&eloop->free_events); + if (e != NULL) + TAILQ_REMOVE(&eloop->free_events, e, next); + else { + e = malloc(sizeof(*e)); + if (e == NULL) + return -1; + TAILQ_INSERT_HEAD(&eloop->events, e, next); + } + e->fd = fd; + eloop->nevents++; } - /* Ensure we can actually listen to it. */ - eloop->events_len++; -#ifdef HAVE_POLL - if (eloop->events_len > eloop->fds_len) { - nfds = eloop_realloca(eloop->fds, - (eloop->fds_len + 5), sizeof(*eloop->fds)); - if (nfds == NULL) - goto err; - eloop->fds_len += 5; - eloop->fds = nfds; - } -#endif - - /* Now populate the structure and add it to the list. */ - e->fd = fd; e->read_cb = read_cb; e->read_cb_arg = read_cb_arg; e->write_cb = write_cb; e->write_cb_arg = write_cb_arg; -#if defined(HAVE_KQUEUE) - if (read_cb != NULL) - EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ, - EV_ADD, 0, 0, UPTR(e)); - if (write_cb != NULL) - EV_SET(&ke[1], (uintptr_t)fd, EVFILT_WRITE, - EV_ADD, 0, 0, UPTR(e)); - if (kevent(eloop->poll_fd, ke, write_cb ? 2 : 1, NULL, 0, NULL) == -1) - goto err; -#elif defined(HAVE_EPOLL) - epe.data.ptr = e; - if (epoll_ctl(eloop->poll_fd, EPOLL_CTL_ADD, fd, &epe) == -1) - goto err; -#endif - - TAILQ_INSERT_HEAD(&eloop->events, e, next); - eloop->event_fds[e->fd] = e; eloop_event_setup_fds(eloop); return 0; - -err: - if (e) { - eloop->events_len--; - TAILQ_INSERT_TAIL(&eloop->free_events, e, next); - } - return -1; } int @@ -519,17 +361,14 @@ eloop_event_delete_write(struct eloop *eloop, int fd, int write_only) { struct eloop_event *e; -#if defined(HAVE_KQUEUE) - struct kevent ke[2]; -#elif defined(HAVE_EPOLL) - struct epoll_event epe; -#endif assert(eloop != NULL); - if (fd > eloop->events_maxfd || - (e = eloop->event_fds[fd]) == NULL) - { + TAILQ_FOREACH(e, &eloop->events, next) { + if (e->fd == fd) + break; + } + if (e == NULL) { errno = ENOENT; return -1; } @@ -541,41 +380,15 @@ goto remove; e->write_cb = NULL; e->write_cb_arg = NULL; -#if defined(HAVE_KQUEUE) - EV_SET(&ke[0], (uintptr_t)e->fd, - EVFILT_WRITE, EV_DELETE, 0, 0, UPTR(NULL)); - kevent(eloop->poll_fd, ke, 1, NULL, 0, NULL); -#elif defined(HAVE_EPOLL) - memset(&epe, 0, sizeof(epe)); - epe.data.fd = e->fd; - epe.data.ptr = e; - epe.events = EPOLLIN; - epoll_ctl(eloop->poll_fd, EPOLL_CTL_MOD, fd, &epe); -#endif - eloop_event_setup_fds(eloop); - return 1; + goto done; } remove: TAILQ_REMOVE(&eloop->events, e, next); - eloop->event_fds[e->fd] = NULL; TAILQ_INSERT_TAIL(&eloop->free_events, e, next); - eloop->events_len--; + eloop->nevents--; -#if defined(HAVE_KQUEUE) - EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ, - EV_DELETE, 0, 0, UPTR(NULL)); - if (e->write_cb) - EV_SET(&ke[1], (uintptr_t)fd, - EVFILT_WRITE, EV_DELETE, 0, 0, UPTR(NULL)); - kevent(eloop->poll_fd, ke, e->write_cb ? 2 : 1, NULL, 0, NULL); -#elif defined(HAVE_EPOLL) - /* NULL event is safe because we - * rely on epoll_pwait which as added - * after the delete without event was fixed. */ - epoll_ctl(eloop->poll_fd, EPOLL_CTL_DEL, fd, NULL); -#endif - +done: eloop_event_setup_fds(eloop); return 1; } @@ -681,7 +494,6 @@ (unsigned int)seconds, (unsigned int)nseconds, callback, arg); } -#if !defined(HAVE_KQUEUE) static int eloop_timeout_add_now(struct eloop *eloop, void (*callback)(void *), void *arg) @@ -692,7 +504,6 @@ eloop->timeout0_arg = arg; return 0; } -#endif int eloop_q_timeout_delete(struct eloop *eloop, int queue, @@ -734,106 +545,7 @@ eloop->exitnow = 0; } -#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) -static int -eloop_open(struct eloop *eloop) -{ - -#if defined(HAVE_KQUEUE1) - return (eloop->poll_fd = kqueue1(O_CLOEXEC)); -#elif defined(HAVE_KQUEUE) - int i; - - if ((eloop->poll_fd = kqueue()) == -1) - return -1; - if ((i = fcntl(eloop->poll_fd, F_GETFD, 0)) == -1 || - fcntl(eloop->poll_fd, F_SETFD, i | FD_CLOEXEC) == -1) - { - close(eloop->poll_fd); - eloop->poll_fd = -1; - } - - return eloop->poll_fd; -#elif defined (HAVE_EPOLL) - return (eloop->poll_fd = epoll_create1(EPOLL_CLOEXEC)); -#else - return (eloop->poll_fd = -1); -#endif -} -#endif - -int -eloop_requeue(struct eloop *eloop) -{ -#if defined(HAVE_POLL) - - UNUSED(eloop); - return 0; -#else /* !HAVE_POLL */ - struct eloop_event *e; - int error; -#if defined(HAVE_KQUEUE) - size_t i; - struct kevent *ke; -#elif defined(HAVE_EPOLL) - struct epoll_event epe; -#endif - - assert(eloop != NULL); - - if (eloop->poll_fd != -1) - close(eloop->poll_fd); - if (eloop_open(eloop) == -1) - return -1; -#if defined (HAVE_KQUEUE) - i = eloop->signals_len; - TAILQ_FOREACH(e, &eloop->events, next) { - i++; - if (e->write_cb) - i++; - } - - if ((ke = malloc(sizeof(*ke) * i)) == NULL) - return -1; - - for (i = 0; i < eloop->signals_len; i++) - EV_SET(&ke[i], (uintptr_t)eloop->signals[i], - EVFILT_SIGNAL, EV_ADD, 0, 0, UPTR(NULL)); - - TAILQ_FOREACH(e, &eloop->events, next) { - EV_SET(&ke[i], (uintptr_t)e->fd, EVFILT_READ, - EV_ADD, 0, 0, UPTR(e)); - i++; - if (e->write_cb) { - EV_SET(&ke[i], (uintptr_t)e->fd, EVFILT_WRITE, - EV_ADD, 0, 0, UPTR(e)); - i++; - } - } - - error = kevent(eloop->poll_fd, ke, LENC(i), NULL, 0, NULL); - free(ke); - -#elif defined(HAVE_EPOLL) - - error = 0; - TAILQ_FOREACH(e, &eloop->events, next) { - memset(&epe, 0, sizeof(epe)); - epe.data.fd = e->fd; - epe.events = EPOLLIN; - if (e->write_cb) - epe.events |= EPOLLOUT; - epe.data.ptr = e; - if (epoll_ctl(eloop->poll_fd, EPOLL_CTL_ADD, e->fd, &epe) == -1) - error = -1; - } -#endif - - return error; -#endif /* HAVE_POLL */ -} - -int +void eloop_signal_set_cb(struct eloop *eloop, const int *signals, size_t signals_len, void (*signal_cb)(int, void *), void *signal_cb_ctx) @@ -845,10 +557,8 @@ eloop->signals_len = signals_len; eloop->signal_cb = signal_cb; eloop->signal_cb_ctx = signal_cb_ctx; - return eloop_requeue(eloop); } -#ifndef HAVE_KQUEUE struct eloop_siginfo { int sig; struct eloop *eloop; @@ -876,16 +586,16 @@ eloop_timeout_add_now(_eloop_siginfo.eloop, eloop_signal1, &_eloop_siginfo); } -#endif int eloop_signal_mask(struct eloop *eloop, sigset_t *oldset) { sigset_t newset; size_t i; -#ifndef HAVE_KQUEUE - struct sigaction sa; -#endif + struct sigaction sa = { + .sa_sigaction = eloop_signal3, + .sa_flags = SA_SIGINFO, + }; assert(eloop != NULL); @@ -895,19 +605,13 @@ if (sigprocmask(SIG_SETMASK, &newset, oldset) == -1) return -1; -#ifndef HAVE_KQUEUE _eloop = eloop; - - memset(&sa, 0, sizeof(sa)); - sa.sa_sigaction = eloop_signal3; - sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); for (i = 0; i < eloop->signals_len; i++) { if (sigaction(eloop->signals[i], &sa, NULL) == -1) return -1; } -#endif return 0; } @@ -927,19 +631,11 @@ } TAILQ_INIT(&eloop->events); - eloop->events_maxfd = -1; TAILQ_INIT(&eloop->free_events); TAILQ_INIT(&eloop->timeouts); TAILQ_INIT(&eloop->free_timeouts); eloop->exitcode = EXIT_FAILURE; -#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) - if (eloop_open(eloop) == -1) { - eloop_free(eloop); - return NULL; - } -#endif - return eloop; } @@ -952,10 +648,7 @@ if (eloop == NULL) return; - free(eloop->event_fds); - eloop->event_fds = NULL; - eloop->events_len = 0; - eloop->events_maxfd = -1; + eloop->nevents = 0; eloop->signals = NULL; eloop->signals_len = 0; @@ -976,21 +669,15 @@ free(t); } -#if defined(HAVE_POLL) free(eloop->fds); eloop->fds = NULL; - eloop->fds_len = 0; -#endif + eloop->nfds = 0; } void eloop_free(struct eloop *eloop) { -#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) - if (eloop != NULL) - close(eloop->poll_fd); -#endif eloop_clear(eloop); free(eloop); } @@ -1002,18 +689,7 @@ struct eloop_event *e; struct eloop_timeout *t; void (*t0)(void *); -#if defined(HAVE_KQUEUE) - struct kevent ke; - UNUSED(signals); -#elif defined(HAVE_EPOLL) - struct epoll_event epe; -#endif -#if defined(HAVE_KQUEUE) || defined(HAVE_POLL) struct timespec ts, *tsp; -#endif -#ifndef HAVE_KQUEUE - int timeout; -#endif assert(eloop != NULL); @@ -1030,7 +706,7 @@ } t = TAILQ_FIRST(&eloop->timeouts); - if (t == NULL && eloop->events_len == 0) + if (t == NULL && eloop->nevents == 0) break; if (t != NULL) @@ -1044,7 +720,6 @@ } if (t != NULL) { -#if defined(HAVE_KQUEUE) || defined(HAVE_POLL) if (t->seconds > INT_MAX) { ts.tv_sec = (time_t)INT_MAX; ts.tv_nsec = 0; @@ -1053,43 +728,10 @@ ts.tv_nsec = (long)t->nseconds; } tsp = &ts; -#endif - -#ifndef HAVE_KQUEUE - if (t->seconds > INT_MAX / 1000 || - (t->seconds == INT_MAX / 1000 && - ((t->nseconds + 999999) / 1000000 - > INT_MAX % 1000000))) - timeout = INT_MAX; - else - timeout = (int)(t->seconds * 1000 + - (t->nseconds + 999999) / 1000000); -#endif - } else { -#if defined(HAVE_KQUEUE) || defined(HAVE_POLL) + } else tsp = NULL; -#endif -#ifndef HAVE_KQUEUE - timeout = -1; -#endif - } -#if defined(HAVE_KQUEUE) - n = kevent(eloop->poll_fd, NULL, 0, &ke, 1, tsp); -#elif defined(HAVE_EPOLL) - if (signals) - n = epoll_pwait(eloop->poll_fd, &epe, 1, - timeout, signals); - else - n = epoll_wait(eloop->poll_fd, &epe, 1, timeout); -#elif defined(HAVE_POLL) - if (signals) - n = POLLTS(eloop->fds, (nfds_t)eloop->events_len, - tsp, signals); - else - n = poll(eloop->fds, (nfds_t)eloop->events_len, - timeout); -#endif + n = ppoll(eloop->fds, (nfds_t)eloop->nevents, tsp, signals); if (n == -1) { if (errno == EINTR) continue; @@ -1098,47 +740,20 @@ if (n == 0) continue; - /* Process any triggered events. - * We go back to the start after calling each callback incase - * the current event or next event is removed. */ -#if defined(HAVE_KQUEUE) - if (ke.filter == EVFILT_SIGNAL) { - eloop->signal_cb((int)ke.ident, - eloop->signal_cb_ctx); - } else { - e = (struct eloop_event *)ke.udata; - if (ke.filter == EVFILT_WRITE && e->write_cb != NULL) - e->write_cb(e->write_cb_arg); - else if (ke.filter == EVFILT_READ && e->read_cb != NULL) - e->read_cb(e->read_cb_arg); - } -#elif defined(HAVE_EPOLL) - e = (struct eloop_event *)epe.data.ptr; - if (epe.events & EPOLLOUT && e->write_cb != NULL) - e->write_cb(e->write_cb_arg); - else if (epe.events & (EPOLLIN | EPOLLERR | EPOLLHUP) && - e->read_cb != NULL) - e->read_cb(e->read_cb_arg); -#elif defined(HAVE_POLL) - size_t i; - - for (i = 0; i < eloop->events_len; i++) { - if (eloop->fds[i].revents & POLLOUT) { - e = eloop->event_fds[eloop->fds[i].fd]; + TAILQ_FOREACH(e, &eloop->events, next) { + if (e->pollfd->revents & POLLOUT) { if (e->write_cb != NULL) { e->write_cb(e->write_cb_arg); break; } } - if (eloop->fds[i].revents) { - e = eloop->event_fds[eloop->fds[i].fd]; + if (e->pollfd->revents) { if (e->read_cb != NULL) { e->read_cb(e->read_cb_arg); break; } } } -#endif } return eloop->exitcode;
--- a/src/eloop.h Wed Jun 03 23:12:59 2020 +0100 +++ b/src/eloop.h Wed Jun 03 23:30:08 2020 +0100 @@ -83,12 +83,11 @@ unsigned long, void (*)(void *), void *); int eloop_q_timeout_delete(struct eloop *, int, void (*)(void *), void *); -int eloop_signal_set_cb(struct eloop *, const int *, size_t, +void eloop_signal_set_cb(struct eloop *, const int *, size_t, void (*)(int, void *), void *); int eloop_signal_mask(struct eloop *, sigset_t *oldset); struct eloop * eloop_new(void); -int eloop_requeue(struct eloop *); void eloop_clear(struct eloop *); void eloop_free(struct eloop *); void eloop_exit(struct eloop *, int);
--- a/src/privsep-root.c Wed Jun 03 23:12:59 2020 +0100 +++ b/src/privsep-root.c Wed Jun 03 23:30:08 2020 +0100 @@ -788,10 +788,9 @@ if ((ctx->ps_eloop = eloop_new()) == NULL) return -1; - if (eloop_signal_set_cb(ctx->ps_eloop, + eloop_signal_set_cb(ctx->ps_eloop, dhcpcd_signals, dhcpcd_signals_len, - ps_root_readerrorsig, ctx) == -1) - return -1; + ps_root_readerrorsig, ctx); return pid; }
--- a/src/privsep.c Wed Jun 03 23:12:59 2020 +0100 +++ b/src/privsep.c Wed Jun 03 23:30:08 2020 +0100 @@ -243,12 +243,8 @@ ctx->ps_inet_fd = -1; } - if (eloop_signal_set_cb(ctx->eloop, - dhcpcd_signals, dhcpcd_signals_len, signal_cb, ctx) == -1) - { - logerr("%s: eloop_signal_set_cb", __func__); - goto errexit; - } + eloop_signal_set_cb(ctx->eloop, + dhcpcd_signals, dhcpcd_signals_len, signal_cb, ctx); /* ctx->sigset aready has the initial sigmask set in main() */ if (eloop_signal_mask(ctx->eloop, NULL) == -1) {
