1e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* 2e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * dhcpcd - DHCP client daemon 3a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt * Copyright (c) 2006-2010 Roy Marples <roy@marples.name> 4e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * All rights reserved 5e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 6e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * Redistribution and use in source and binary forms, with or without 7e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * modification, are permitted provided that the following conditions 8e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * are met: 9e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * 1. Redistributions of source code must retain the above copyright 10e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * notice, this list of conditions and the following disclaimer. 11e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * 2. Redistributions in binary form must reproduce the above copyright 12e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * notice, this list of conditions and the following disclaimer in the 13e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * documentation and/or other materials provided with the distribution. 14e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * 15e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * SUCH DAMAGE. 26e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt */ 27e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 28e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/time.h> 29e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 30e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <errno.h> 31e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <limits.h> 32e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <poll.h> 33e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <stdarg.h> 34e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <stdlib.h> 35e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <syslog.h> 36e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 37e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "common.h" 38e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "eloop.h" 39e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 40e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct timeval now; 41e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 42e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct event { 43e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int fd; 44e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt void (*callback)(void *); 45e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt void *arg; 46e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct event *next; 47e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} *events; 48e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct event *free_events; 49e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 50e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct timeout { 51e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct timeval when; 52e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt void (*callback)(void *); 53e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt void *arg; 54e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int queue; 55e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct timeout *next; 56e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} *timeouts; 57e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct timeout *free_timeouts; 58e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 59e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct pollfd *fds; 60e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic size_t fds_len; 61e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 62e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 63e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtadd_event(int fd, void (*callback)(void *), void *arg) 64e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 65e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct event *e, *last = NULL; 66e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 67e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We should only have one callback monitoring the fd */ 68e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (e = events; e; e = e->next) { 69e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (e->fd == fd) { 70e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e->callback = callback; 71e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e->arg = arg; 72e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 73e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 74e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt last = e; 75e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 76e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 77e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Allocate a new event if no free ones already allocated */ 78e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (free_events) { 79e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = free_events; 80e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_events = e->next; 81e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else 82e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = xmalloc(sizeof(*e)); 83e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e->fd = fd; 84e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e->callback = callback; 85e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e->arg = arg; 86e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e->next = NULL; 87e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (last) 88e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt last->next = e; 89e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 90e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt events = e; 91e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 92e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 93e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 94e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdelete_event(int fd) 95e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 96e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct event *e, *last = NULL; 97e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 98e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (e = events; e; e = e->next) { 99e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (e->fd == fd) { 100e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (last) 101e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt last->next = e->next; 102e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 103e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt events = e->next; 104e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e->next = free_events; 105e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_events = e; 106e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 107e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 108e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt last = e; 109e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 110e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 111e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 112e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 113e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtadd_q_timeout_tv(int queue, 114e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt const struct timeval *when, void (*callback)(void *), void *arg) 115e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 116e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct timeval w; 117e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct timeout *t, *tt = NULL; 118e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 119e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt get_monotonic(&now); 120e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt timeradd(&now, when, &w); 121e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Check for time_t overflow. */ 122e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (timercmp(&w, &now, <)) { 123e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt errno = ERANGE; 124e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 125e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 126e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 127e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Remove existing timeout if present */ 128e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (t = timeouts; t; t = t->next) { 129e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (t->callback == callback && t->arg == arg) { 130e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (tt) 131e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt tt->next = t->next; 132e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 133e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt timeouts = t->next; 134e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 135e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 136e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt tt = t; 137e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 138e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 139e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!t) { 140e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* No existing, so allocate or grab one from the free pool */ 141e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (free_timeouts) { 142e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t = free_timeouts; 143e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_timeouts = t->next; 144e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else 145e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t = xmalloc(sizeof(*t)); 146e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 147e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 148e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t->when.tv_sec = w.tv_sec; 149e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t->when.tv_usec = w.tv_usec; 150e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t->callback = callback; 151e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t->arg = arg; 152e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t->queue = queue; 153e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 154e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* The timeout list should be in chronological order, 155e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * soonest first. 156e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * This is the easiest algorithm - check the head, then middle 157e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * and finally the end. */ 158e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!timeouts || timercmp(&t->when, &timeouts->when, <)) { 159e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t->next = timeouts; 160e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt timeouts = t; 161e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 162e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 163e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (tt = timeouts; tt->next; tt = tt->next) 164e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (timercmp(&t->when, &tt->next->when, <)) { 165e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t->next = tt->next; 166e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt tt->next = t; 167e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 168e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 169e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt tt->next = t; 170e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t->next = NULL; 171e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 172e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 173e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 174e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtadd_q_timeout_sec(int queue, time_t when, void (*callback)(void *), void *arg) 175e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 176e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct timeval tv; 177e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 178e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt tv.tv_sec = when; 179e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt tv.tv_usec = 0; 180e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_q_timeout_tv(queue, &tv, callback, arg); 181e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 182e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 183e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* This deletes all timeouts for the interface EXCEPT for ones with the 184e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * callbacks given. Handy for deleting everything apart from the expire 185e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * timeout. */ 186e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 187e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtv_delete_q_timeouts(int queue, void *arg, void (*callback)(void *), va_list v) 188e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 189e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct timeout *t, *tt, *last = NULL; 190e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt va_list va; 191e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt void (*f)(void *); 192e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 193e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (t = timeouts; t && (tt = t->next, 1); t = tt) { 194e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (t->queue == queue && t->arg == arg && 195e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t->callback != callback) 196e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 197e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt va_copy(va, v); 198e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while ((f = va_arg(va, void (*)(void *)))) 199e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (f == t->callback) 200e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 201e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt va_end(va); 202e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!f) { 203e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (last) 204e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt last->next = t->next; 205e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 206e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt timeouts = t->next; 207e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t->next = free_timeouts; 208e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_timeouts = t; 209e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 210e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 211e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 212e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt last = t; 213e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 214e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 215e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 216e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 217e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdelete_q_timeouts(int queue, void *arg, void (*callback)(void *), ...) 218e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 219e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt va_list va; 220e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 221e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt va_start(va, callback); 222e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt v_delete_q_timeouts(queue, arg, callback, va); 223e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt va_end(va); 224e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 225e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 226e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 227e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdelete_q_timeout(int queue, void (*callback)(void *), void *arg) 228e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 229e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct timeout *t, *tt, *last = NULL; 230e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 231e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (t = timeouts; t && (tt = t->next, 1); t = tt) { 232e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (t->queue == queue && t->arg == arg && 233e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (!callback || t->callback == callback)) 234e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt { 235e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (last) 236e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt last->next = t->next; 237e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 238e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt timeouts = t->next; 239e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t->next = free_timeouts; 240e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_timeouts = t; 241e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 242e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 243e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt last = t; 244e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 245e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 246e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 247e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef DEBUG_MEMORY 248e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* Define this to free all malloced memory. 249e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * Normally we don't do this as the OS will do it for us at exit, 250e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * but it's handy for debugging other leaks in valgrind. */ 251e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void 252e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtcleanup(void) 253e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 254e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct event *e; 255e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct timeout *t; 256e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 257e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (events) { 258e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = events->next; 259e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(events); 260e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt events = e; 261e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 262e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (free_events) { 263e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e = free_events->next; 264e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(free_events); 265e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_events = e; 266e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 267e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (timeouts) { 268e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t = timeouts->next; 269e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(timeouts); 270e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt timeouts = t; 271e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 272e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt while (free_timeouts) { 273e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t = free_timeouts->next; 274e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(free_timeouts); 275e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_timeouts = t; 276e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 277e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(fds); 278e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 279e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 280e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 281e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt_noreturn void 282e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_eloop(void) 283e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 284e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt int msecs, n; 285e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt nfds_t nfds, i; 286e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct event *e; 287e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct timeout *t; 288e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct timeval tv; 289e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 290e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef DEBUG_MEMORY 291e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt atexit(cleanup); 292e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif 293e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 294e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (;;) { 295e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Run all timeouts first. 296e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * When we have one that has not yet occured, 297e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * calculate milliseconds until it does for use in poll. */ 298e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (timeouts) { 299e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (timercmp(&now, &timeouts->when, >)) { 300e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t = timeouts; 301e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt timeouts = timeouts->next; 302e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t->callback(t->arg); 303e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt t->next = free_timeouts; 304e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free_timeouts = t; 305e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 306e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 307e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt timersub(&timeouts->when, &now, &tv); 308e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (tv.tv_sec > INT_MAX / 1000 || 309e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (tv.tv_sec == INT_MAX / 1000 && 310e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (tv.tv_usec + 999) / 1000 > INT_MAX % 1000)) 311e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt msecs = INT_MAX; 312e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 313e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt msecs = tv.tv_sec * 1000 + 314e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (tv.tv_usec + 999) / 1000; 315e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else 316e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* No timeouts, so wait forever. */ 317e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt msecs = -1; 318e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 319e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Allocate memory for our pollfds as and when needed. 320e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * We don't bother shrinking it. */ 321e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt nfds = 0; 322e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (e = events; e; e = e->next) 323e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt nfds++; 324e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (msecs == -1 && nfds == 0) { 325e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "nothing to do"); 326e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 327e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 328e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (nfds > fds_len) { 329e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(fds); 330e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Allocate 5 more than we need for future use */ 331e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt fds_len = nfds + 5; 332e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt fds = xmalloc(sizeof(*fds) * fds_len); 333e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 334e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt nfds = 0; 335e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (e = events; e; e = e->next) { 336e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt fds[nfds].fd = e->fd; 337e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt fds[nfds].events = POLLIN; 338e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt fds[nfds].revents = 0; 339e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt nfds++; 340e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 341e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt n = poll(fds, nfds, msecs); 342e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (n == -1) { 343e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (errno == EAGAIN || errno == EINTR) { 344e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt get_monotonic(&now); 345e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 346e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 347e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "poll: %m"); 348e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt exit(EXIT_FAILURE); 349e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 350e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 351e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Get the now time and process any triggered events. */ 352e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt get_monotonic(&now); 353e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (n == 0) 354e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 355e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (i = 0; i < nfds; i++) { 356e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!(fds[i].revents & (POLLIN | POLLHUP))) 357e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt continue; 358e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (e = events; e; e = e->next) { 359e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (e->fd == fds[i].fd) { 360e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt e->callback(e->arg); 361e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 362e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 363e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 364e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 365e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 366e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 367