1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * eloop - portable event based main loop. 4 * Copyright (c) 2006-2025 Roy Marples <roy (at) marples.name> 5 * All rights reserved. 6 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #if (defined(__unix__) || defined(unix)) && !defined(USG) 30 #include <sys/param.h> 31 #endif 32 #include <sys/time.h> 33 34 /* 35 * On BSD use kqueue(2) 36 * On Linux use epoll(7) 37 * Everywhere else use ppoll(2) 38 */ 39 #ifdef BSD 40 #include <sys/event.h> 41 #define USE_KQUEUE 42 #if defined(__NetBSD__) 43 #define HAVE_KQUEUE1 44 #define KEVENT_N size_t 45 #else 46 #define KEVENT_N int 47 #endif 48 #elif defined(__linux__) 49 #include <sys/epoll.h> 50 #define USE_EPOLL 51 /* musl does not support epoll_wait2 and some distros 52 * mismatch headers vs actual kernel so it's too problematic. */ 53 #else 54 #define USE_PPOLL 55 #endif 56 57 #include <errno.h> 58 #include <fcntl.h> 59 #include <limits.h> 60 #include <poll.h> 61 #include <signal.h> 62 #include <stdbool.h> 63 #include <stdint.h> 64 #include <stdlib.h> 65 #include <string.h> 66 #include <unistd.h> 67 68 #include "eloop.h" 69 #include "queue.h" 70 71 /* 72 * Allow a backlog of signals. 73 * If you use many eloops in the same process, they should all 74 * use the same signal handler or have the signal handler unset. 75 * Otherwise the signal might not behave as expected. 76 */ 77 #define ELOOP_NSIGNALS 5 78 79 /* 80 * time_t is a signed integer of an unspecified size. 81 * To adjust for time_t wrapping, we need to work the maximum signed 82 * value and use that as a maximum. 83 */ 84 #ifndef TIME_MAX 85 #define TIME_MAX ((1ULL << (sizeof(time_t) * NBBY - 1)) - 1) 86 #endif 87 /* The unsigned maximum is then simple - multiply by two and add one. */ 88 #ifndef UTIME_MAX 89 #define UTIME_MAX (TIME_MAX * 2) + 1 90 #endif 91 92 #ifndef UNUSED 93 #define UNUSED(a) (void)(a) 94 #endif 95 96 struct eloop_event { 97 TAILQ_ENTRY(eloop_event) next; 98 int fd; 99 void (*cb)(void *, unsigned short); 100 void *cb_arg; 101 unsigned short events; 102 #ifdef USE_PPOLL 103 struct pollfd *pollfd; 104 #endif 105 }; 106 107 struct eloop_timeout { 108 TAILQ_ENTRY(eloop_timeout) next; 109 unsigned int seconds; 110 unsigned int nseconds; 111 void (*callback)(void *); 112 void *arg; 113 int queue; 114 }; 115 116 struct eloop { 117 TAILQ_ENTRY(eloop) next; 118 TAILQ_HEAD(event_head, eloop_event) events; 119 size_t nevents; 120 struct event_head free_events; 121 122 struct timespec now; 123 TAILQ_HEAD(timeout_head, eloop_timeout) timeouts; 124 struct timeout_head free_timeouts; 125 126 const int *signals; 127 size_t nsignals; 128 sigset_t sigset; 129 void (*signal_cb)(int, void *); 130 void *signal_cb_ctx; 131 132 #if defined(USE_KQUEUE) || defined(USE_EPOLL) 133 int fd; 134 #endif 135 #if defined(USE_KQUEUE) 136 struct kevent *fds; 137 #elif defined(USE_EPOLL) 138 struct epoll_event *fds; 139 #elif defined(USE_PPOLL) 140 struct pollfd *fds; 141 #endif 142 size_t nfds; 143 144 int exitcode; 145 bool exitnow; 146 bool events_need_setup; 147 bool events_invalid; 148 }; 149 150 #ifdef HAVE_REALLOCARRAY 151 #define eloop_realloca reallocarray 152 #else 153 /* Handy routing to check for potential overflow. 154 * reallocarray(3) and reallocarr(3) are not portable. */ 155 #define SQRT_SIZE_MAX (((size_t)1) << (sizeof(size_t) * CHAR_BIT / 2)) 156 static void * 157 eloop_realloca(void *ptr, size_t n, size_t size) 158 { 159 if ((n | size) >= SQRT_SIZE_MAX && n > SIZE_MAX / size) { 160 errno = EOVERFLOW; 161 return NULL; 162 } 163 return realloc(ptr, n * size); 164 } 165 #endif 166 167 static int 168 eloop_event_setup_fds(struct eloop *eloop) 169 { 170 struct eloop_event *e, *ne; 171 #ifdef USE_PPOLL 172 struct pollfd *pfd; 173 174 if (eloop->nevents > eloop->nfds) { 175 pfd = eloop_realloca(eloop->fds, eloop->nevents, sizeof(*pfd)); 176 if (pfd == NULL) 177 return -1; 178 eloop->fds = pfd; 179 eloop->nfds = eloop->nevents; 180 } else 181 pfd = eloop->fds; 182 #endif 183 184 TAILQ_FOREACH_SAFE(e, &eloop->events, next, ne) { 185 if (e->fd == -1) { 186 TAILQ_REMOVE(&eloop->events, e, next); 187 TAILQ_INSERT_TAIL(&eloop->free_events, e, next); 188 continue; 189 } 190 #ifdef USE_PPOLL 191 e->pollfd = pfd; 192 pfd->fd = e->fd; 193 pfd->events = 0; 194 if (e->events & ELE_READ) 195 pfd->events |= POLLIN; 196 if (e->events & ELE_WRITE) 197 pfd->events |= POLLOUT; 198 pfd->revents = 0; 199 pfd++; 200 #endif 201 } 202 203 eloop->events_need_setup = false; 204 return 0; 205 } 206 207 #ifndef USE_PPOLL 208 static int 209 eloop_grow_events(struct eloop *eloop) 210 { 211 #if defined(USE_KQUEUE) 212 struct kevent *pfd; 213 #elif defined(USE_EPOLL) 214 struct epoll_event *pfd; 215 #endif 216 size_t nfds = eloop->nfds == 0 ? 4 : eloop->nfds * 2; 217 218 pfd = eloop_realloca(eloop->fds, nfds, sizeof(*pfd)); 219 if (pfd == NULL) 220 return -1; 221 eloop->fds = pfd; 222 eloop->nfds = nfds; 223 return 0; 224 } 225 #endif 226 227 size_t 228 eloop_event_count(const struct eloop *eloop) 229 { 230 return eloop->nevents; 231 } 232 233 #if defined(USE_KQUEUE) 234 235 static int 236 eloop_signal_kqueue(struct eloop *eloop, const int *signals, size_t nsignals) 237 { 238 unsigned int cmd = nsignals == 0 ? EV_DELETE : EV_ADD; 239 struct kevent *ke, *kep; 240 size_t i; 241 int err; 242 243 if (nsignals == 0) { 244 signals = eloop->signals; 245 nsignals = eloop->nsignals; 246 } 247 if (nsignals == 0) 248 return 0; 249 250 ke = kep = eloop_realloca(NULL, nsignals, sizeof(*ke)); 251 if (ke == NULL) 252 return -1; 253 254 for (i = 0; i < nsignals; i++) 255 EV_SET(kep++, (uintptr_t)signals[i], EVFILT_SIGNAL, cmd, 0, 0, 256 NULL); 257 258 err = kevent(eloop->fd, ke, (KEVENT_N)nsignals, NULL, 0, NULL); 259 free(ke); 260 return err; 261 } 262 263 static int 264 eloop_event_kqueue(struct eloop *eloop, struct eloop_event *e, 265 unsigned short events) 266 { 267 #ifdef EVFILT_PROCDESC 268 #define NKE 3 269 #else 270 #define NKE 2 271 #endif 272 struct kevent ke[NKE], *kep = ke; 273 int fd = e->fd; 274 275 if (events & ELE_READ && !(e->events & ELE_READ)) 276 EV_SET(kep++, (uintptr_t)fd, EVFILT_READ, EV_ADD, 0, 0, e); 277 else if (!(events & ELE_READ) && e->events & ELE_READ) 278 EV_SET(kep++, (uintptr_t)fd, EVFILT_READ, EV_DELETE, 0, 0, e); 279 if (events & ELE_WRITE && !(e->events & ELE_WRITE)) 280 EV_SET(kep++, (uintptr_t)fd, EVFILT_WRITE, EV_ADD, 0, 0, e); 281 else if (!(events & ELE_WRITE) && e->events & ELE_WRITE) 282 EV_SET(kep++, (uintptr_t)fd, EVFILT_WRITE, EV_DELETE, 0, 0, e); 283 #ifdef EVFILT_PROCDESC 284 if (events & ELE_HANGUP && !(e->events & ELE_HANGUP)) 285 EV_SET(kep++, (uintptr_t)fd, EVFILT_PROCDESC, EV_ADD, NOTE_EXIT, 286 0, e); 287 else if (!(events & ELE_HANGUP) && e->events & ELE_HANGUP) 288 EV_SET(kep++, (uintptr_t)fd, EVFILT_PROCDESC, EV_DELETE, 289 NOTE_EXIT, 0, e); 290 #endif 291 if (kep == ke) 292 return 0; 293 if (kevent(eloop->fd, ke, (KEVENT_N)(kep - ke), NULL, 0, NULL) == -1) 294 return -1; 295 return 1; 296 } 297 298 #elif defined(USE_EPOLL) 299 300 static int 301 eloop_event_epoll(struct eloop *eloop, struct eloop_event *e, 302 unsigned short events) 303 { 304 struct epoll_event epe; 305 int op; 306 307 memset(&epe, 0, sizeof(epe)); 308 epe.data.ptr = e; 309 if (events & ELE_READ) 310 epe.events |= EPOLLIN; 311 if (events & ELE_WRITE) 312 epe.events |= EPOLLOUT; 313 op = e->events == 0 ? EPOLL_CTL_ADD : EPOLL_CTL_MOD; 314 if (epe.events == 0) 315 return 0; 316 if (epoll_ctl(eloop->fd, op, e->fd, &epe) == -1) 317 return -1; 318 return 1; 319 } 320 #endif 321 322 int 323 eloop_event_add(struct eloop *eloop, int fd, unsigned short events, 324 void (*cb)(void *, unsigned short), void *cb_arg) 325 { 326 struct eloop_event *e; 327 bool added; 328 int kadded; 329 330 if (fd == -1 || !(events & (ELE_READ | ELE_WRITE | ELE_HANGUP))) { 331 errno = EINVAL; 332 return -1; 333 } 334 335 TAILQ_FOREACH(e, &eloop->events, next) { 336 if (e->fd == fd) 337 break; 338 } 339 340 if (e == NULL) { 341 added = true; 342 e = TAILQ_FIRST(&eloop->free_events); 343 if (e != NULL) 344 TAILQ_REMOVE(&eloop->free_events, e, next); 345 else { 346 e = malloc(sizeof(*e)); 347 if (e == NULL) { 348 return -1; 349 } 350 } 351 TAILQ_INSERT_HEAD(&eloop->events, e, next); 352 eloop->nevents++; 353 e->fd = fd; 354 e->events = 0; 355 } else 356 added = false; 357 358 e->cb = cb; 359 e->cb_arg = cb_arg; 360 361 #if defined(USE_KQUEUE) 362 kadded = eloop_event_kqueue(eloop, e, events); 363 #elif defined(USE_EPOLL) 364 kadded = eloop_event_epoll(eloop, e, events); 365 #elif defined(USE_PPOLL) 366 e->pollfd = NULL; 367 kadded = 1; 368 #endif 369 370 if (kadded != 1 && added) { 371 TAILQ_REMOVE(&eloop->events, e, next); 372 TAILQ_INSERT_TAIL(&eloop->free_events, e, next); 373 } 374 375 e->events = events; 376 eloop->events_need_setup = true; 377 return kadded; 378 } 379 380 int 381 eloop_event_delete(struct eloop *eloop, int fd) 382 { 383 struct eloop_event *e; 384 #if defined(USE_KQUEUE) 385 struct kevent ke[2], *kep = &ke[0]; 386 size_t n; 387 #endif 388 389 if (fd == -1) { 390 errno = EINVAL; 391 return -1; 392 } 393 394 TAILQ_FOREACH(e, &eloop->events, next) { 395 if (e->fd == fd) 396 break; 397 } 398 if (e == NULL) { 399 errno = ENOENT; 400 return -1; 401 } 402 403 #if defined(USE_KQUEUE) 404 n = 0; 405 if (e->events & ELE_READ) { 406 EV_SET(kep++, (uintptr_t)fd, EVFILT_READ, EV_DELETE, 0, 0, e); 407 n++; 408 } 409 if (e->events & ELE_WRITE) { 410 EV_SET(kep++, (uintptr_t)fd, EVFILT_WRITE, EV_DELETE, 0, 0, e); 411 n++; 412 } 413 if (n != 0 && kevent(eloop->fd, ke, (KEVENT_N)n, NULL, 0, NULL) == -1) 414 return -1; 415 #elif defined(USE_EPOLL) 416 if (epoll_ctl(eloop->fd, EPOLL_CTL_DEL, fd, NULL) == -1) 417 return -1; 418 #endif 419 420 e->fd = -1; 421 eloop->nevents--; 422 eloop->events_need_setup = true; 423 return 1; 424 } 425 426 unsigned long long 427 eloop_timespec_diff(const struct timespec *tsp, const struct timespec *usp, 428 unsigned int *nsp) 429 { 430 unsigned long long tsecs, usecs, secs; 431 long nsecs; 432 433 if (tsp->tv_sec < 0) /* time wrapped */ 434 tsecs = UTIME_MAX - (unsigned long long)(-tsp->tv_sec); 435 else 436 tsecs = (unsigned long long)tsp->tv_sec; 437 if (usp->tv_sec < 0) /* time wrapped */ 438 usecs = UTIME_MAX - (unsigned long long)(-usp->tv_sec); 439 else 440 usecs = (unsigned long long)usp->tv_sec; 441 442 if (usecs > tsecs) /* time wrapped */ 443 secs = (UTIME_MAX - usecs) + tsecs; 444 else 445 secs = tsecs - usecs; 446 447 nsecs = tsp->tv_nsec - usp->tv_nsec; 448 if (nsecs < 0) { 449 if (secs == 0) 450 nsecs = 0; 451 else { 452 secs--; 453 nsecs += NSEC_PER_SEC; 454 } 455 } 456 if (nsp != NULL) 457 *nsp = (unsigned int)nsecs; 458 return secs; 459 } 460 461 static int 462 eloop_reduce_timers(struct eloop *eloop) 463 { 464 struct timespec now; 465 unsigned long long secs; 466 unsigned int nsecs; 467 struct eloop_timeout *t; 468 469 if (clock_gettime(CLOCK_MONOTONIC, &now) == -1) 470 return -1; 471 secs = eloop_timespec_diff(&now, &eloop->now, &nsecs); 472 473 TAILQ_FOREACH(t, &eloop->timeouts, next) { 474 if (secs > t->seconds) { 475 t->seconds = 0; 476 t->nseconds = 0; 477 } else { 478 t->seconds -= (unsigned int)secs; 479 if (nsecs > t->nseconds) { 480 if (t->seconds == 0) 481 t->nseconds = 0; 482 else { 483 t->seconds--; 484 t->nseconds = NSEC_PER_SEC - 485 (nsecs - t->nseconds); 486 } 487 } else 488 t->nseconds -= nsecs; 489 } 490 } 491 492 eloop->now = now; 493 return 0; 494 } 495 496 /* 497 * This implementation should cope with UINT_MAX seconds on a system 498 * where time_t is INT32_MAX. It should also cope with the monotonic timer 499 * wrapping, although this is highly unlikely. 500 * unsigned int should match or be greater than any on wire specified timeout. 501 */ 502 static int 503 eloop_q_timeout_add(struct eloop *eloop, int queue, unsigned int seconds, 504 unsigned int nseconds, void (*callback)(void *), void *arg) 505 { 506 struct eloop_timeout *t, *tt = NULL; 507 508 /* Remove existing timeout if present. */ 509 TAILQ_FOREACH(t, &eloop->timeouts, next) { 510 if (t->callback == callback && t->arg == arg) { 511 TAILQ_REMOVE(&eloop->timeouts, t, next); 512 break; 513 } 514 } 515 516 if (eloop_reduce_timers(eloop) == -1) { 517 if (t != NULL) 518 free(t); 519 return -1; 520 } 521 522 if (t == NULL) { 523 /* No existing, so allocate or grab one from the free pool. */ 524 if ((t = TAILQ_FIRST(&eloop->free_timeouts))) { 525 TAILQ_REMOVE(&eloop->free_timeouts, t, next); 526 } else { 527 if ((t = malloc(sizeof(*t))) == NULL) 528 return -1; 529 } 530 } 531 532 t->seconds = seconds; 533 t->nseconds = nseconds; 534 t->callback = callback; 535 t->arg = arg; 536 t->queue = queue; 537 538 /* The timeout list should be in chronological order, 539 * soonest first. */ 540 TAILQ_FOREACH(tt, &eloop->timeouts, next) { 541 if (t->seconds < tt->seconds || 542 (t->seconds == tt->seconds && t->nseconds < tt->nseconds)) { 543 TAILQ_INSERT_BEFORE(tt, t, next); 544 return 0; 545 } 546 } 547 TAILQ_INSERT_TAIL(&eloop->timeouts, t, next); 548 return 0; 549 } 550 551 int 552 eloop_q_timeout_add_tv(struct eloop *eloop, int queue, 553 const struct timespec *when, void (*callback)(void *), void *arg) 554 { 555 if (when->tv_sec < 0 || (unsigned long)when->tv_sec > UINT_MAX) { 556 errno = EINVAL; 557 return -1; 558 } 559 if (when->tv_nsec < 0 || when->tv_nsec > NSEC_PER_SEC) { 560 errno = EINVAL; 561 return -1; 562 } 563 564 return eloop_q_timeout_add(eloop, queue, (unsigned int)when->tv_sec, 565 (unsigned int)when->tv_sec, callback, arg); 566 } 567 568 int 569 eloop_q_timeout_add_sec(struct eloop *eloop, int queue, unsigned int seconds, 570 void (*callback)(void *), void *arg) 571 { 572 return eloop_q_timeout_add(eloop, queue, seconds, 0, callback, arg); 573 } 574 575 int 576 eloop_q_timeout_add_msec(struct eloop *eloop, int queue, unsigned long when, 577 void (*callback)(void *), void *arg) 578 { 579 unsigned long seconds, nseconds; 580 581 seconds = when / MSEC_PER_SEC; 582 if (seconds > UINT_MAX) { 583 errno = EINVAL; 584 return -1; 585 } 586 587 nseconds = (when % MSEC_PER_SEC) * NSEC_PER_MSEC; 588 return eloop_q_timeout_add(eloop, queue, (unsigned int)seconds, 589 (unsigned int)nseconds, callback, arg); 590 } 591 592 int 593 eloop_q_timeout_delete(struct eloop *eloop, int queue, void (*callback)(void *), 594 void *arg) 595 { 596 struct eloop_timeout *t, *tt; 597 int n; 598 599 n = 0; 600 TAILQ_FOREACH_SAFE(t, &eloop->timeouts, next, tt) { 601 if ((queue == 0 || t->queue == queue) && t->arg == arg && 602 (!callback || t->callback == callback)) { 603 TAILQ_REMOVE(&eloop->timeouts, t, next); 604 TAILQ_INSERT_TAIL(&eloop->free_timeouts, t, next); 605 n++; 606 } 607 } 608 return n; 609 } 610 611 void 612 eloop_exit(struct eloop *eloop, int code) 613 { 614 eloop->exitcode = code; 615 eloop->exitnow = true; 616 } 617 618 #if defined(USE_KQUEUE) || defined(USE_EPOLL) 619 static int 620 eloop_open(struct eloop *eloop) 621 { 622 int fd; 623 624 #if defined(HAVE_KQUEUE1) 625 fd = kqueue1(O_CLOEXEC); 626 #elif defined(KQUEUE_CLOEXEC) 627 fd = kqueuex(KQUEUE_CLOEXEC); 628 #elif defined(USE_KQUEUE) 629 int flags; 630 631 fd = kqueue(); 632 flags = fcntl(fd, F_GETFD, 0); 633 if (!(flags != -1 && !(flags & FD_CLOEXEC) && 634 fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0)) { 635 close(fd); 636 return -1; 637 } 638 #elif defined(USE_EPOLL) 639 fd = epoll_create1(EPOLL_CLOEXEC); 640 #endif 641 642 eloop->fd = fd; 643 return fd; 644 } 645 #endif 646 647 static void 648 eloop_clear(struct eloop *eloop, unsigned short flags) 649 { 650 if (eloop == NULL) 651 return; 652 653 if (!(flags & ELF_KEEP_SIGNALS)) { 654 eloop->signals = NULL; 655 eloop->nsignals = 0; 656 eloop->signal_cb = NULL; 657 eloop->signal_cb_ctx = NULL; 658 } 659 660 if (!(flags & ELF_KEEP_EVENTS)) { 661 struct eloop_event *e, *en; 662 663 TAILQ_FOREACH_SAFE(e, &eloop->events, next, en) 664 free(e); 665 TAILQ_INIT(&eloop->events); 666 667 TAILQ_FOREACH_SAFE(e, &eloop->free_events, next, en) 668 free(e); 669 TAILQ_INIT(&eloop->free_events); 670 671 eloop->nevents = 0; 672 eloop->events_invalid = true; 673 } 674 675 if (!(flags & ELF_KEEP_TIMEOUTS)) { 676 struct eloop_timeout *t, *tn; 677 678 TAILQ_FOREACH_SAFE(t, &eloop->timeouts, next, tn) 679 free(t); 680 TAILQ_INIT(&eloop->timeouts); 681 682 TAILQ_FOREACH_SAFE(t, &eloop->free_timeouts, next, tn) 683 free(t); 684 TAILQ_INIT(&eloop->free_timeouts); 685 } 686 } 687 688 /* Must be called after fork(2) */ 689 int 690 eloop_forked(struct eloop *eloop, unsigned short flags) 691 { 692 #if defined(USE_KQUEUE) || defined(USE_EPOLL) 693 struct eloop_event *e; 694 unsigned short events; 695 int err; 696 697 /* The fd is invalid after a fork, no need to close it. */ 698 eloop->fd = -1; 699 if (flags && eloop_open(eloop) == -1) 700 return -1; 701 702 eloop_clear(eloop, flags); 703 if (!flags) 704 return 0; 705 706 #ifdef USE_KQUEUE 707 if (eloop_signal_kqueue(eloop, eloop->signals, eloop->nsignals) == -1) 708 return -1; 709 #endif 710 711 TAILQ_FOREACH(e, &eloop->events, next) { 712 if (e->fd == -1) 713 continue; 714 events = e->events; 715 e->events = 0; 716 #if defined(USE_KQUEUE) 717 err = eloop_event_kqueue(eloop, e, events); 718 #elif defined(USE_EPOLL) 719 err = eloop_event_epoll(eloop, e, events); 720 #endif 721 if (err == -1) 722 return -1; 723 } 724 return 0; 725 #else 726 eloop_clear(eloop, flags); 727 return 0; 728 #endif 729 } 730 731 int 732 eloop_signal_set_cb(struct eloop *eloop, const int *signals, size_t nsignals, 733 void (*signal_cb)(int, void *), void *signal_cb_ctx) 734 { 735 #ifdef USE_KQUEUE 736 if (eloop_signal_kqueue(eloop, NULL, 0) == -1) 737 return -1; 738 #endif 739 740 eloop->signals = signals; 741 eloop->nsignals = nsignals; 742 eloop->signal_cb = signal_cb; 743 eloop->signal_cb_ctx = signal_cb_ctx; 744 745 #ifdef USE_KQUEUE 746 if (eloop_signal_kqueue(eloop, signals, nsignals) == -1) 747 return -1; 748 #endif 749 750 return 0; 751 } 752 753 #ifndef USE_KQUEUE 754 static volatile int eloop_sig[ELOOP_NSIGNALS]; 755 static volatile size_t eloop_nsig; 756 757 static void 758 eloop_signal3(int sig, siginfo_t *siginfo, void *arg) 759 { 760 (void)(siginfo); 761 (void)(arg); 762 763 if (eloop_nsig == sizeof(eloop_sig) / sizeof(eloop_sig[0])) { 764 #ifdef ELOOP_DEBUG 765 fprintf(stderr, "%s: signal storm, discarding signal %d\n", 766 __func__, sig); 767 #endif 768 return; 769 } 770 eloop_sig[eloop_nsig++] = sig; 771 } 772 #endif 773 774 int 775 eloop_signal_mask(struct eloop *eloop) 776 { 777 sigset_t newset; 778 size_t i; 779 #ifndef USE_KQUEUE 780 struct sigaction sa = { 781 .sa_sigaction = eloop_signal3, 782 .sa_flags = SA_SIGINFO, 783 }; 784 #endif 785 786 sigemptyset(&newset); 787 for (i = 0; i < eloop->nsignals; i++) 788 sigaddset(&newset, eloop->signals[i]); 789 if (sigprocmask(SIG_SETMASK, &newset, &eloop->sigset) == -1) 790 return -1; 791 792 #ifndef USE_KQUEUE 793 sigemptyset(&sa.sa_mask); 794 795 for (i = 0; i < eloop->nsignals; i++) { 796 if (sigaction(eloop->signals[i], &sa, NULL) == -1) 797 return -1; 798 } 799 #endif 800 801 return 0; 802 } 803 804 struct eloop * 805 eloop_new(void) 806 { 807 struct eloop *eloop; 808 809 eloop = calloc(1, sizeof(*eloop)); 810 if (eloop == NULL) 811 return NULL; 812 813 /* Check we have a working monotonic clock. */ 814 if (clock_gettime(CLOCK_MONOTONIC, &eloop->now) == -1) { 815 free(eloop); 816 return NULL; 817 } 818 819 TAILQ_INIT(&eloop->events); 820 TAILQ_INIT(&eloop->free_events); 821 TAILQ_INIT(&eloop->timeouts); 822 TAILQ_INIT(&eloop->free_timeouts); 823 eloop->exitcode = EXIT_FAILURE; 824 825 #if defined(USE_KQUEUE) || defined(USE_EPOLL) 826 if (eloop_open(eloop) == -1 || eloop_grow_events(eloop) == -1) { 827 eloop_free(eloop); 828 return NULL; 829 } 830 #endif 831 832 return eloop; 833 } 834 835 void 836 eloop_free(struct eloop *eloop) 837 { 838 if (eloop == NULL) 839 return; 840 841 eloop_clear(eloop, 0); 842 #if defined(USE_KQUEUE) || defined(USE_EPOLL) 843 if (eloop->fd != -1) 844 close(eloop->fd); 845 #endif 846 free(eloop->fds); 847 free(eloop); 848 } 849 850 static unsigned short 851 eloop_pollevents(struct pollfd *pfd) 852 { 853 unsigned short events = 0; 854 855 if (pfd->revents & POLLIN) 856 events |= ELE_READ; 857 if (pfd->revents & POLLOUT) 858 events |= ELE_WRITE; 859 if (pfd->revents & POLLHUP) 860 events |= ELE_HANGUP; 861 if (pfd->revents & POLLERR) 862 events |= ELE_ERROR; 863 if (pfd->revents & POLLNVAL) 864 events |= ELE_NVAL; 865 return events; 866 } 867 868 int 869 eloop_waitfd(int fd) 870 { 871 struct pollfd pfd = { .fd = fd, .events = POLLIN }; 872 int err; 873 874 err = ppoll(&pfd, 1, NULL, NULL); 875 if (err == -1 || err == 0) 876 return err; 877 878 return (int)eloop_pollevents(&pfd); 879 } 880 881 #if defined(USE_KQUEUE) 882 883 static int 884 eloop_run_kqueue(struct eloop *eloop, const struct timespec *ts) 885 { 886 int n, nn; 887 struct kevent *ke; 888 struct eloop_event *e; 889 unsigned short events; 890 891 n = kevent(eloop->fd, NULL, 0, eloop->fds, (KEVENT_N)eloop->nfds, ts); 892 if (n == -1) 893 return -1; 894 895 for (nn = n, ke = eloop->fds; nn != 0; nn--, ke++) { 896 if (eloop->exitnow || eloop->events_invalid) 897 break; 898 if (ke->filter == EVFILT_SIGNAL) { 899 if (eloop->signal_cb != NULL) 900 eloop->signal_cb((int)ke->ident, 901 eloop->signal_cb_ctx); 902 continue; 903 } 904 if (ke->filter == EVFILT_READ) 905 events = ELE_READ; 906 else if (ke->filter == EVFILT_WRITE) 907 events = ELE_WRITE; 908 #ifdef EVFILT_PROCDESC 909 else if (ke->filter == EVFILT_PROCDESC && 910 ke->fflags & NOTE_EXIT) 911 /* exit status is in ke->data 912 * should we do anything with it? */ 913 events = ELE_HANGUP; 914 #endif 915 else 916 continue; /* assert? */ 917 if (ke->flags & EV_EOF) 918 events |= ELE_HANGUP; 919 if (ke->flags & EV_ERROR) 920 events |= ELE_ERROR; 921 e = (struct eloop_event *)ke->udata; 922 e->cb(e->cb_arg, events); 923 } 924 925 if ((size_t)n == eloop->nfds) 926 eloop_grow_events(eloop); 927 return n; 928 } 929 930 #elif defined(USE_EPOLL) 931 932 static int 933 eloop_run_epoll(struct eloop *eloop, const struct timespec *ts) 934 { 935 int n, nn; 936 struct epoll_event *epe; 937 struct eloop_event *e; 938 unsigned short events; 939 940 /* epoll does not work with zero events */ 941 if (eloop->nfds == 0) 942 n = ppoll(NULL, 0, ts, &eloop->sigset); 943 else { 944 int timeout; 945 946 if (ts != NULL) { 947 if (ts->tv_sec > INT_MAX / MSEC_PER_SEC || 948 (ts->tv_sec == INT_MAX / MSEC_PER_SEC && 949 ((ts->tv_nsec + (NSEC_PER_MSEC - 1)) / 950 NSEC_PER_MSEC > 951 INT_MAX % NSEC_PER_MSEC))) 952 timeout = INT_MAX; 953 else 954 timeout = (int)(ts->tv_sec * MSEC_PER_SEC + 955 (ts->tv_nsec + (NSEC_PER_MSEC - 1)) / 956 NSEC_PER_MSEC); 957 } else 958 timeout = -1; 959 960 n = epoll_pwait(eloop->fd, eloop->fds, (int)eloop->nfds, 961 timeout, &eloop->sigset); 962 } 963 if (n == -1) 964 return -1; 965 966 for (nn = n, epe = eloop->fds; nn != 0; nn--, epe++) { 967 if (eloop->exitnow || eloop->events_invalid) 968 break; 969 e = (struct eloop_event *)epe->data.ptr; 970 if (e->fd == -1) 971 continue; 972 events = 0; 973 if (epe->events & EPOLLIN) 974 events |= ELE_READ; 975 if (epe->events & EPOLLOUT) 976 events |= ELE_WRITE; 977 if (epe->events & EPOLLHUP) 978 events |= ELE_HANGUP; 979 if (epe->events & EPOLLERR) 980 events |= ELE_ERROR; 981 e->cb(e->cb_arg, events); 982 } 983 984 if ((size_t)n == eloop->nfds) 985 eloop_grow_events(eloop); 986 return n; 987 } 988 989 #elif defined(USE_PPOLL) 990 991 static int 992 eloop_run_ppoll(struct eloop *eloop, const struct timespec *ts) 993 { 994 int n, nn; 995 struct eloop_event *e; 996 struct pollfd *pfd; 997 unsigned short events; 998 999 n = ppoll(eloop->fds, (nfds_t)eloop->nevents, ts, &eloop->sigset); 1000 if (n == -1 || n == 0) 1001 return n; 1002 1003 nn = n; 1004 TAILQ_FOREACH(e, &eloop->events, next) { 1005 if (eloop->exitnow || eloop->events_invalid) 1006 break; 1007 /* Skip freshly added events */ 1008 if ((pfd = e->pollfd) == NULL) 1009 continue; 1010 if (e->pollfd->revents) { 1011 nn--; 1012 events = eloop_pollevents(pfd); 1013 if (events) 1014 e->cb(e->cb_arg, events); 1015 } 1016 if (nn == 0) 1017 break; 1018 } 1019 return n; 1020 } 1021 1022 #endif 1023 1024 int 1025 eloop_start(struct eloop *eloop) 1026 { 1027 int error; 1028 struct eloop_timeout *t; 1029 struct timespec ts, *tsp; 1030 1031 eloop->exitnow = false; 1032 1033 for (;;) { 1034 if (eloop->exitnow) 1035 break; 1036 if (eloop->events_invalid) { 1037 eloop->events_invalid = false; 1038 eloop->events_need_setup = true; 1039 } 1040 1041 #ifndef USE_KQUEUE 1042 if (eloop_nsig != 0) { 1043 int sig = eloop_sig[--eloop_nsig]; 1044 1045 if (eloop->signal_cb != NULL) 1046 eloop->signal_cb(sig, eloop->signal_cb_ctx); 1047 continue; 1048 } 1049 #endif 1050 1051 t = TAILQ_FIRST(&eloop->timeouts); 1052 if (t == NULL && eloop->nevents == 0) 1053 break; 1054 1055 if (t != NULL) 1056 eloop_reduce_timers(eloop); 1057 1058 if (t != NULL && t->seconds == 0 && t->nseconds == 0) { 1059 TAILQ_REMOVE(&eloop->timeouts, t, next); 1060 t->callback(t->arg); 1061 TAILQ_INSERT_TAIL(&eloop->free_timeouts, t, next); 1062 continue; 1063 } 1064 1065 if (t != NULL) { 1066 if (t->seconds > INT_MAX) { 1067 ts.tv_sec = (time_t)INT_MAX; 1068 ts.tv_nsec = 0; 1069 } else { 1070 ts.tv_sec = (time_t)t->seconds; 1071 ts.tv_nsec = (long)t->nseconds; 1072 } 1073 tsp = &ts; 1074 } else 1075 tsp = NULL; 1076 1077 if (eloop->events_need_setup) 1078 eloop_event_setup_fds(eloop); 1079 1080 #if defined(USE_KQUEUE) 1081 error = eloop_run_kqueue(eloop, tsp); 1082 #elif defined(USE_EPOLL) 1083 error = eloop_run_epoll(eloop, tsp); 1084 #elif defined(USE_PPOLL) 1085 error = eloop_run_ppoll(eloop, tsp); 1086 #endif 1087 if (error == -1) { 1088 if (errno == EINTR) 1089 continue; 1090 return -errno; 1091 } 1092 } 1093 1094 return eloop->exitcode; 1095 } 1096