1d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* 2d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * dhcpcd - DHCP client daemon 3d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Copyright (c) 2006-2015 Roy Marples <roy@marples.name> 4d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * All rights reserved 5d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 6d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Redistribution and use in source and binary forms, with or without 7d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * modification, are permitted provided that the following conditions 8d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * are met: 9d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 1. Redistributions of source code must retain the above copyright 10d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * notice, this list of conditions and the following disclaimer. 11d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 2. Redistributions in binary form must reproduce the above copyright 12d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * notice, this list of conditions and the following disclaimer in the 13d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * documentation and/or other materials provided with the distribution. 14d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 15d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * SUCH DAMAGE. 26d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan */ 27d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 28d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/time.h> 29d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 30d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <errno.h> 31d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <limits.h> 32d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <signal.h> 33d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <stdlib.h> 34d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <string.h> 35d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <unistd.h> 36d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 37d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "config.h" 38d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "common.h" 39d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "dhcpcd.h" 40d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "eloop.h" 41d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 42d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_KQUEUE) 43d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/event.h> 44d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <fcntl.h> 45d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef __NetBSD__ 46d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* udata is void * except on NetBSD 47d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * lengths are int except on NetBSD */ 48d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define UPTR(x) ((intptr_t)(x)) 49d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define LENC(x) (x) 50d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 51d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define UPTR(x) (x) 52d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define LENC(x) ((int)(x)) 53d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 54d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define eloop_event_setup_fds(ctx) 55d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(HAVE_EPOLL) 56d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/epoll.h> 57d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define eloop_event_setup_fds(ctx) 58d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 59d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <poll.h> 60d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void 61d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneloop_event_setup_fds(struct eloop_ctx *ctx) 62d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 63d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct eloop_event *e; 64d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t i; 65d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 66d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i = 0; 67d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_FOREACH(e, &ctx->events, next) { 68d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->fds[i].fd = e->fd; 69d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->fds[i].events = 0; 70d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (e->read_cb) 71d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->fds[i].events |= POLLIN; 72d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (e->write_cb) 73d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->fds[i].events |= POLLOUT; 74d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->fds[i].revents = 0; 75d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->pollfd = &ctx->fds[i]; 76d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i++; 77d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 78d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 79d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 80d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 81d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 82d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneloop_event_add(struct eloop_ctx *ctx, int fd, 83d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan void (*read_cb)(void *), void *read_cb_arg, 84d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan void (*write_cb)(void *), void *write_cb_arg) 85d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 86d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct eloop_event *e; 87d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_KQUEUE) 88d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct kevent ke[2]; 89d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(HAVE_EPOLL) 90d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct epoll_event epe; 91d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 92d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct pollfd *nfds; 93d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 94d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 95d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef HAVE_EPOLL 96d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&epe, 0, sizeof(epe)); 97d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan epe.data.fd = fd; 98d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan epe.events = EPOLLIN; 99d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (write_cb) 100d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan epe.events |= EPOLLOUT; 101d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 102d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 103d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* We should only have one callback monitoring the fd */ 104d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_FOREACH(e, &ctx->events, next) { 105d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (e->fd == fd) { 106d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int error; 107d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 108d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_KQUEUE) 109d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ, EV_ADD, 110d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 0, 0, UPTR(e)); 111d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (write_cb) 112d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_SET(&ke[1], (uintptr_t)fd, EVFILT_WRITE, 113d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_ADD, 0, 0, UPTR(e)); 114d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (e->write_cb) 115d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_SET(&ke[1], (uintptr_t)fd, EVFILT_WRITE, 116d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_DELETE, 0, 0, UPTR(e)); 117d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan error = kevent(ctx->poll_fd, ke, 118d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->write_cb || write_cb ? 2 : 1, NULL, 0, NULL); 119d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(HAVE_EPOLL) 120d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan epe.data.ptr = e; 121d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan error = epoll_ctl(ctx->poll_fd, EPOLL_CTL_MOD, 122d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fd, &epe); 123d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 124d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan error = 0; 125d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 126d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (read_cb) { 127d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->read_cb = read_cb; 128d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->read_cb_arg = read_cb_arg; 129d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 130d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (write_cb) { 131d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->write_cb = write_cb; 132d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->write_cb_arg = write_cb_arg; 133d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 134d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan eloop_event_setup_fds(ctx); 135d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return error; 136d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 137d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 138d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 139d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Allocate a new event if no free ones already allocated */ 140d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((e = TAILQ_FIRST(&ctx->free_events))) { 141d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_REMOVE(&ctx->free_events, e, next); 142d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else { 143d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e = malloc(sizeof(*e)); 144d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (e == NULL) 145d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto err; 146d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 147d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 148d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Ensure we can actually listen to it */ 149d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->events_len++; 150d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if !defined(HAVE_KQUEUE) && !defined(HAVE_EPOLL) 151d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ctx->events_len > ctx->fds_len) { 152d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan nfds = realloc(ctx->fds, sizeof(*ctx->fds) * (ctx->fds_len+5)); 153d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (nfds == NULL) 154d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto err; 155d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->fds_len += 5; 156d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->fds = nfds; 157d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 158d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 159d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 160d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Now populate the structure and add it to the list */ 161d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->fd = fd; 162d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->read_cb = read_cb; 163d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->read_cb_arg = read_cb_arg; 164d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->write_cb = write_cb; 165d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->write_cb_arg = write_cb_arg; 166d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 167d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_KQUEUE) 168d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ, EV_ADD, 0, 0, UPTR(e)); 169d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (write_cb) 170d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_SET(&ke[1], (uintptr_t)fd, EVFILT_WRITE, 171d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_ADD, 0, 0, UPTR(e)); 172d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (kevent(ctx->poll_fd, ke, write_cb ? 2 : 1, NULL, 0, NULL) == -1) 173d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto err; 174d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(HAVE_EPOLL) 175d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan epe.data.ptr = e; 176d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (epoll_ctl(ctx->poll_fd, EPOLL_CTL_ADD, fd, &epe) == -1) 177d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan goto err; 178d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 179d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 180d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* The order of events should not matter. 181d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * However, some PPP servers love to close the link right after 182d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * sending their final message. So to ensure dhcpcd processes this 183d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * message (which is likely to be that the DHCP addresses are wrong) 184d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * we insert new events at the queue head as the link fd will be 185d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * the first event added. */ 186d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_INSERT_HEAD(&ctx->events, e, next); 187d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan eloop_event_setup_fds(ctx); 188d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 189d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 190d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanerr: 191d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ctx->ctx, LOG_ERR, "%s: %m", __func__); 192d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (e) { 193d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->events_len--; 194d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_INSERT_TAIL(&ctx->free_events, e, next); 195d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 196d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 197d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 198d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 199d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid 200d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneloop_event_delete(struct eloop_ctx *ctx, int fd, int write_only) 201d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 202d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct eloop_event *e; 203d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_KQUEUE) 204d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct kevent ke[2]; 205d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(HAVE_EPOLL) 206d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct epoll_event epe; 207d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 208d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 209d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_FOREACH(e, &ctx->events, next) { 210d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (e->fd == fd) { 211d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (write_only) { 212d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (e->write_cb) { 213d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->write_cb = NULL; 214d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->write_cb_arg = NULL; 215d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_KQUEUE) 216d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_SET(&ke[0], (uintptr_t)fd, 217d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EVFILT_WRITE, EV_DELETE, 218d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 0, 0, UPTR(NULL)); 219d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan kevent(ctx->poll_fd, ke, 1, NULL, 0, 220d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan NULL); 221d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(HAVE_EPOLL) 222d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&epe, 0, sizeof(epe)); 223d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan epe.data.fd = e->fd; 224d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan epe.data.ptr = e; 225d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan epe.events = EPOLLIN; 226d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan epoll_ctl(ctx->poll_fd, EPOLL_CTL_MOD, 227d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fd, &epe); 228d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 229d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 230d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 231d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else { 232d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_REMOVE(&ctx->events, e, next); 233d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_KQUEUE) 234d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_SET(&ke[0], (uintptr_t)fd, EVFILT_READ, 235d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_DELETE, 0, 0, UPTR(NULL)); 236d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (e->write_cb) 237d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_SET(&ke[1], (uintptr_t)fd, 238d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EVFILT_WRITE, EV_DELETE, 239d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 0, 0, UPTR(NULL)); 240d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan kevent(ctx->poll_fd, ke, e->write_cb ? 2 : 1, 241d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan NULL, 0, NULL); 242d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(HAVE_EPOLL) 243d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* NULL event is safe because we 244d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * rely on epoll_pwait which as added 245d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * after the delete without event was fixed. */ 246d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan epoll_ctl(ctx->poll_fd, EPOLL_CTL_DEL, 247d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fd, NULL); 248d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 249d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_INSERT_TAIL(&ctx->free_events, e, next); 250d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->events_len--; 251d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 252d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan eloop_event_setup_fds(ctx); 253d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 254d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 255d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 256d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 257d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 258d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 259d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneloop_q_timeout_add_tv(struct eloop_ctx *ctx, int queue, 260d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const struct timespec *when, void (*callback)(void *), void *arg) 261d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 262d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct timespec now, w; 263d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct eloop_timeout *t, *tt = NULL; 264d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 265d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan get_monotonic(&now); 266d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan timespecadd(&now, when, &w); 267d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Check for time_t overflow. */ 268d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (timespeccmp(&w, &now, <)) { 269d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ERANGE; 270d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 271d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 272d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 273d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Remove existing timeout if present */ 274d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_FOREACH(t, &ctx->timeouts, next) { 275d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (t->callback == callback && t->arg == arg) { 276d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_REMOVE(&ctx->timeouts, t, next); 277d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 278d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 279d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 280d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 281d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (t == NULL) { 282d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* No existing, so allocate or grab one from the free pool */ 283d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((t = TAILQ_FIRST(&ctx->free_timeouts))) { 284d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_REMOVE(&ctx->free_timeouts, t, next); 285d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else { 286d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan t = malloc(sizeof(*t)); 287d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (t == NULL) { 288d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ctx->ctx, LOG_ERR, "%s: %m", __func__); 289d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 290d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 291d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 292d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 293d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 294d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan t->when = w; 295d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan t->callback = callback; 296d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan t->arg = arg; 297d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan t->queue = queue; 298d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 299d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* The timeout list should be in chronological order, 300d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * soonest first. */ 301d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_FOREACH(tt, &ctx->timeouts, next) { 302d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (timespeccmp(&t->when, &tt->when, <)) { 303d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_INSERT_BEFORE(tt, t, next); 304d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 305d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 306d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 307d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_INSERT_TAIL(&ctx->timeouts, t, next); 308d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 309d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 310d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 311d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 312d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneloop_q_timeout_add_sec(struct eloop_ctx *ctx, int queue, time_t when, 313d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan void (*callback)(void *), void *arg) 314d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 315d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct timespec tv; 316d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 317d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan tv.tv_sec = when; 318d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan tv.tv_nsec = 0; 319d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return eloop_q_timeout_add_tv(ctx, queue, &tv, callback, arg); 320d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 321d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 322d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if !defined(HAVE_KQUEUE) 323d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 324d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneloop_timeout_add_now(struct eloop_ctx *ctx, 325d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan void (*callback)(void *), void *arg) 326d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 327d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 328d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ctx->timeout0 != NULL) { 329d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ctx->ctx, LOG_WARNING, 330d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: timeout0 already set", __func__); 331d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return eloop_q_timeout_add_sec(ctx, 0, 0, callback, arg); 332d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 333d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 334d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->timeout0 = callback; 335d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->timeout0_arg = arg; 336d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 337d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 338d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 339d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 340d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid 341d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneloop_q_timeout_delete(struct eloop_ctx *ctx, int queue, 342d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan void (*callback)(void *), void *arg) 343d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 344d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct eloop_timeout *t, *tt; 345d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 346d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_FOREACH_SAFE(t, &ctx->timeouts, next, tt) { 347d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((queue == 0 || t->queue == queue) && 348d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan t->arg == arg && 349d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (!callback || t->callback == callback)) 350d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 351d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_REMOVE(&ctx->timeouts, t, next); 352d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_INSERT_TAIL(&ctx->free_timeouts, t, next); 353d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 354d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 355d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 356d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 357d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid 358d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneloop_exit(struct eloop_ctx *ctx, int code) 359d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 360d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 361d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->exitcode = code; 362d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->exitnow = 1; 363d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 364d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 365d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) 366d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 367d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneloop_open(struct eloop_ctx *ctx) 368d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 369d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_KQUEUE1) 370d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return (ctx->poll_fd = kqueue1(O_CLOEXEC)); 371d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(HAVE_KQUEUE) 372d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int i; 373d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 374d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((ctx->poll_fd = kqueue()) == -1) 375d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 376d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((i = fcntl(ctx->poll_fd, F_GETFD, 0)) == -1 || 377d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fcntl(ctx->poll_fd, F_SETFD, i | FD_CLOEXEC) == -1) 378d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 379d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(ctx->poll_fd); 380d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->poll_fd = -1; 381d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 382d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 383d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 384d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return ctx->poll_fd; 385d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined (HAVE_EPOLL) 386d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return (ctx->poll_fd = epoll_create1(EPOLL_CLOEXEC)); 387d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 388d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 389d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 390d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 391d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneloop_requeue(struct eloop_ctx *ctx) 392d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 393d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct eloop_event *e; 394d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int error; 395d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_KQUEUE) 396d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t i; 397d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct kevent *ke; 398d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(HAVE_EPOLL) 399d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct epoll_event epe; 400d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 401d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 402d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ctx->poll_fd != -1) 403d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(ctx->poll_fd); 404d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (eloop_open(ctx) == -1) 405d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 406d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined (HAVE_KQUEUE) 407d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i = 0; 408d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (dhcpcd_handlesigs[i]) 409d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i++; 410d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_FOREACH(e, &ctx->events, next) { 411d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i++; 412d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (e->write_cb) 413d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i++; 414d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 415d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 416d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((ke = malloc(sizeof(*ke) * i)) == NULL) 417d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 418d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 419d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (i = 0; dhcpcd_handlesigs[i]; i++) 420d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_SET(&ke[i], (uintptr_t)dhcpcd_handlesigs[i], 421d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EVFILT_SIGNAL, EV_ADD, 0, 0, UPTR(NULL)); 422d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 423d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_FOREACH(e, &ctx->events, next) { 424d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_SET(&ke[i], (uintptr_t)e->fd, EVFILT_READ, 425d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_ADD, 0, 0, UPTR(e)); 426d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i++; 427d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (e->write_cb) { 428d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_SET(&ke[i], (uintptr_t)e->fd, EVFILT_WRITE, 429d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan EV_ADD, 0, 0, UPTR(e)); 430d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i++; 431d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 432d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 433d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 434d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan error = kevent(ctx->poll_fd, ke, LENC(i), NULL, 0, NULL); 435d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(ke); 436d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 437d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(HAVE_EPOLL) 438d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 439d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan error = 0; 440d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_FOREACH(e, &ctx->events, next) { 441d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memset(&epe, 0, sizeof(epe)); 442d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan epe.data.fd = e->fd; 443d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan epe.events = EPOLLIN; 444d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (e->write_cb) 445d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan epe.events |= EPOLLOUT; 446d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan epe.data.ptr = e; 447d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (epoll_ctl(ctx->poll_fd, EPOLL_CTL_ADD, e->fd, &epe) == -1) 448d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan error = -1; 449d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 450d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 451d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 452d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return error; 453d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 454d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 455d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 456d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstruct eloop_ctx * 457d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneloop_init(struct dhcpcd_ctx *dctx) 458d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 459d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct eloop_ctx *ctx; 460d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct timespec now; 461d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 462d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Check we have a working monotonic clock. */ 463d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (get_monotonic(&now) == -1) 464d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return NULL; 465d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 466d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx = calloc(1, sizeof(*ctx)); 467d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ctx) { 468d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->ctx = dctx; 469d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_INIT(&ctx->events); 470d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_INIT(&ctx->free_events); 471d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_INIT(&ctx->timeouts); 472d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_INIT(&ctx->free_timeouts); 473d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->exitcode = EXIT_FAILURE; 474d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) 475d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->poll_fd = -1; 476d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 477d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (eloop_requeue(ctx) == -1) { 478d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(ctx); 479d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return NULL; 480d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 481d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 482d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 483d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return ctx; 484d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 485d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 486d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid eloop_free(struct eloop_ctx *ctx) 487d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 488d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct eloop_event *e; 489d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct eloop_timeout *t; 490d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 491d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ctx == NULL) 492d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return; 493d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 494d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while ((e = TAILQ_FIRST(&ctx->events))) { 495d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_REMOVE(&ctx->events, e, next); 496d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(e); 497d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 498d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while ((e = TAILQ_FIRST(&ctx->free_events))) { 499d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_REMOVE(&ctx->free_events, e, next); 500d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(e); 501d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 502d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while ((t = TAILQ_FIRST(&ctx->timeouts))) { 503d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_REMOVE(&ctx->timeouts, t, next); 504d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(t); 505d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 506d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while ((t = TAILQ_FIRST(&ctx->free_timeouts))) { 507d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_REMOVE(&ctx->free_timeouts, t, next); 508d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(t); 509d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 510d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) 511d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan close(ctx->poll_fd); 512d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 513d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(ctx->fds); 514d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 515d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(ctx); 516d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 517d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 518d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 519d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Taneloop_start(struct eloop_ctx *ctx) 520d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 521d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int n; 522d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct eloop_event *e; 523d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct eloop_timeout *t; 524d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct timespec now, ts, *tsp; 525d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan void (*t0)(void *); 526d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_EPOLL) || !defined(USE_SIGNALS) 527d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int timeout; 528d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 529d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_KQUEUE) 530d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct kevent ke; 531d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(HAVE_EPOLL) 532d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct epoll_event epe; 533d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 534d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 535d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (;;) { 536d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ctx->exitnow) 537d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 538d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 539d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Run all timeouts first */ 540d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ctx->timeout0) { 541d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan t0 = ctx->timeout0; 542d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ctx->timeout0 = NULL; 543d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan t0(ctx->timeout0_arg); 544d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 545d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 546d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((t = TAILQ_FIRST(&ctx->timeouts))) { 547d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan get_monotonic(&now); 548d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (timespeccmp(&now, &t->when, >)) { 549d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_REMOVE(&ctx->timeouts, t, next); 550d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan t->callback(t->arg); 551d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_INSERT_TAIL(&ctx->free_timeouts, t, next); 552d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 553d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 554d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan timespecsub(&t->when, &now, &ts); 555d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan tsp = &ts; 556d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else 557d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* No timeouts, so wait forever */ 558d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan tsp = NULL; 559d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 560d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (tsp == NULL && ctx->events_len == 0) { 561d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ctx->ctx, LOG_ERR, "nothing to do"); 562d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 563d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 564d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 565d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_EPOLL) || !defined(USE_SIGNALS) 566d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (tsp == NULL) 567d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan timeout = -1; 568d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (tsp->tv_sec > INT_MAX / 1000 || 569d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (tsp->tv_sec == INT_MAX / 1000 && 570d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (tsp->tv_nsec + 999999) / 1000000 > INT_MAX % 1000000)) 571d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan timeout = INT_MAX; 572d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 573d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan timeout = (int)(tsp->tv_sec * 1000 + 574d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (tsp->tv_nsec + 999999) / 1000000); 575d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 576d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 577d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_KQUEUE) 578d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n = kevent(ctx->poll_fd, NULL, 0, &ke, 1, tsp); 579d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(HAVE_EPOLL) 580d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef USE_SIGNALS 581d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n = epoll_pwait(ctx->poll_fd, &epe, 1, timeout, 582d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan &ctx->ctx->sigset); 583d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 584d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n = epoll_wait(ctx->poll_fd, &epe, 1, timeout); 585d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 586d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 587d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef USE_SIGNALS 588d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n = pollts(ctx->fds, (nfds_t)ctx->events_len, tsp, 589d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan &ctx->ctx->sigset); 590d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 591d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n = poll(ctx->fds, (nfds_t)ctx->events_len, timeout); 592d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 593d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 594d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (n == -1) { 595d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (errno == EINTR) 596d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 597d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ctx->ctx, LOG_ERR, "poll: %m"); 598d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 599d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 600d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 601d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Process any triggered events. 602d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * We go back to the start after calling each callback incase 603d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * the current event or next event is removed. */ 604d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#if defined(HAVE_KQUEUE) 605d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (n) { 606d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ke.filter == EVFILT_SIGNAL) { 607d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct dhcpcd_siginfo si; 608d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 609d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan si.signo = (int)ke.ident; 610d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcpcd_handle_signal(&si); 611d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 612d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 613d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e = (struct eloop_event *)ke.udata; 614d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ke.filter == EVFILT_WRITE) { 615d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->write_cb(e->write_cb_arg); 616d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 617d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else if (ke.filter == EVFILT_READ) { 618d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->read_cb(e->read_cb_arg); 619d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 620d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 621d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 622d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#elif defined(HAVE_EPOLL) 623d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (n) { 624d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e = (struct eloop_event *)epe.data.ptr; 625d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (epe.events & EPOLLOUT && e->write_cb) { 626d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->write_cb(e->write_cb_arg); 627d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 628d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 629d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (epe.events & 630d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (EPOLLIN | EPOLLERR | EPOLLHUP)) 631d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 632d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->read_cb(e->read_cb_arg); 633d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 634d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 635d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 636d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 637d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (n > 0) { 638d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_FOREACH(e, &ctx->events, next) { 639d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (e->pollfd->revents & POLLOUT && 640d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->write_cb) 641d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 642d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->write_cb(e->write_cb_arg); 643d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 644d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 645d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (e->pollfd->revents) { 646d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e->read_cb(e->read_cb_arg); 647d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 648d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 649d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 650d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 651d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 652d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 653d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 654d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return ctx->exitcode; 655d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 656