1 /* 2 * uloop - event loop implementation 3 * 4 * Copyright (C) 2010-2016 Felix Fietkau <nbd@openwrt.org> 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 #include <sys/time.h> 19 #include <sys/types.h> 20 21 #include <unistd.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <errno.h> 25 #include <poll.h> 26 #include <string.h> 27 #include <fcntl.h> 28 #include <stdbool.h> 29 #include <limits.h> 30 #include <signal.h> 31 32 #include "uloop.h" 33 #include "utils.h" 34 35 #ifdef USE_KQUEUE 36 #include <sys/event.h> 37 #endif 38 #ifdef USE_EPOLL 39 #include <sys/epoll.h> 40 #include <sys/timerfd.h> 41 #endif 42 #include <sys/wait.h> 43 44 struct uloop_fd_event { 45 struct uloop_fd *fd; 46 unsigned int events; 47 }; 48 49 struct uloop_fd_stack { 50 struct uloop_fd_stack *next; 51 struct uloop_fd *fd; 52 unsigned int events; 53 }; 54 55 static struct uloop_fd_stack *fd_stack = NULL; 56 57 #define ULOOP_MAX_EVENTS 10 58 59 static struct list_head timeouts = LIST_HEAD_INIT(timeouts); 60 static struct list_head processes = LIST_HEAD_INIT(processes); 61 static struct list_head signals = LIST_HEAD_INIT(signals); 62 63 /* 64 * Entries the signal and process dispatch loops are about to visit. A callback 65 * may delete (and free) an arbitrary sibling entry; the matching *_delete() 66 * advances these so the loops never dereference a freed entry. 67 */ 68 static struct uloop_signal *signal_next; 69 static struct uloop_process *process_next; 70 71 static int poll_fd = -1; 72 bool uloop_cancelled = false; 73 bool uloop_handle_sigchld = true; 74 static int uloop_status = 0; 75 static volatile sig_atomic_t do_sigchld = 0; 76 77 static struct uloop_fd_event cur_fds[ULOOP_MAX_EVENTS]; 78 static int cur_fd, cur_nfds; 79 static int uloop_run_depth = 0; 80 81 uloop_fd_handler uloop_fd_set_cb = NULL; 82 83 int uloop_fd_add(struct uloop_fd *sock, unsigned int flags); 84 85 #ifdef USE_KQUEUE 86 #include "uloop-kqueue.c" 87 #endif 88 89 #ifdef USE_EPOLL 90 #include "uloop-epoll.c" 91 #endif 92 93 static void set_signo(uint64_t *signums, int signo) 94 { 95 if (signo >= 1 && signo <= 64) 96 *signums |= (UINT64_C(1) << (signo - 1)); 97 } 98 99 static bool get_signo(uint64_t signums, int signo) 100 { 101 return (signo >= 1) && (signo <= 64) && (signums & (UINT64_C(1) << (signo - 1))); 102 } 103 104 static struct uloop_signal *uloop_signal_next_entry(struct uloop_signal *s) 105 { 106 if (list_is_last(&s->list, &signals)) 107 return NULL; 108 109 return list_next_entry(s, list); 110 } 111 112 static void signal_consume(struct uloop_fd *fd, unsigned int events) 113 { 114 struct uloop_signal *usig; 115 uint64_t signums = 0; 116 uint8_t buf[32]; 117 ssize_t nsigs; 118 119 do { 120 nsigs = read(fd->fd, buf, sizeof(buf)); 121 122 for (ssize_t i = 0; i < nsigs; i++) 123 set_signo(&signums, buf[i]); 124 } 125 while (nsigs > 0); 126 127 signal_next = list_empty(&signals) ? NULL : 128 list_first_entry(&signals, struct uloop_signal, list); 129 130 while ((usig = signal_next) != NULL) { 131 signal_next = uloop_signal_next_entry(usig); 132 if (get_signo(signums, usig->signo)) 133 usig->cb(usig); 134 } 135 } 136 137 static int waker_pipe = -1; 138 static struct uloop_fd waker_fd = { 139 .fd = -1, 140 .cb = signal_consume, 141 }; 142 143 static void waker_init_fd(int fd) 144 { 145 int flags; 146 147 flags = fcntl(fd, F_GETFD); 148 if (flags >= 0) 149 fcntl(fd, F_SETFD, flags | FD_CLOEXEC); 150 151 flags = fcntl(fd, F_GETFL); 152 if (flags >= 0) 153 fcntl(fd, F_SETFL, flags | O_NONBLOCK); 154 } 155 156 static int waker_init(void) 157 { 158 int fds[2]; 159 160 if (waker_pipe >= 0) 161 return 0; 162 163 if (pipe(fds) < 0) 164 return -1; 165 166 waker_init_fd(fds[0]); 167 waker_init_fd(fds[1]); 168 waker_pipe = fds[1]; 169 170 waker_fd.fd = fds[0]; 171 waker_fd.cb = signal_consume; 172 uloop_fd_add(&waker_fd, ULOOP_READ); 173 174 return 0; 175 } 176 177 static void uloop_setup_signals(bool add); 178 179 int uloop_init(void) 180 { 181 if (uloop_init_pollfd() < 0) 182 return -1; 183 184 if (waker_init() < 0) { 185 uloop_done(); 186 return -1; 187 } 188 189 uloop_setup_signals(true); 190 191 return 0; 192 } 193 194 static bool uloop_fd_stack_event(struct uloop_fd *fd, int events) 195 { 196 struct uloop_fd_stack *cur; 197 198 /* 199 * Do not buffer events for level-triggered fds, they will keep firing. 200 * Caller needs to take care of recursion issues. 201 */ 202 if (!(fd->flags & ULOOP_EDGE_TRIGGER)) 203 return false; 204 205 for (cur = fd_stack; cur; cur = cur->next) { 206 if (cur->fd != fd) 207 continue; 208 209 if (events < 0) 210 cur->fd = NULL; 211 else 212 cur->events |= events | ULOOP_EVENT_BUFFERED; 213 214 return true; 215 } 216 217 return false; 218 } 219 220 static void uloop_run_events(int64_t timeout) 221 { 222 struct uloop_fd_event *cur; 223 struct uloop_fd *fd; 224 225 if (!cur_nfds) { 226 cur_fd = 0; 227 cur_nfds = uloop_fetch_events(timeout); 228 if (cur_nfds < 0) 229 cur_nfds = 0; 230 } 231 232 while (cur_nfds > 0) { 233 struct uloop_fd_stack stack_cur; 234 unsigned int events; 235 236 cur = &cur_fds[cur_fd++]; 237 cur_nfds--; 238 239 fd = cur->fd; 240 events = cur->events; 241 if (!fd) 242 continue; 243 244 if (!fd->cb) 245 continue; 246 247 if (uloop_fd_stack_event(fd, cur->events)) 248 continue; 249 250 stack_cur.next = fd_stack; 251 stack_cur.fd = fd; 252 fd_stack = &stack_cur; 253 do { 254 stack_cur.events = 0; 255 fd->cb(fd, events); 256 events = stack_cur.events & ULOOP_EVENT_MASK; 257 } while (stack_cur.fd && events); 258 fd_stack = stack_cur.next; 259 260 return; 261 } 262 } 263 264 int uloop_fd_add(struct uloop_fd *sock, unsigned int flags) 265 { 266 int fl; 267 int ret; 268 269 if (!(flags & (ULOOP_READ | ULOOP_WRITE | ULOOP_PRIORITY))) 270 return uloop_fd_delete(sock); 271 272 if (!sock->registered && !(flags & ULOOP_BLOCKING)) { 273 fl = fcntl(sock->fd, F_GETFL, 0); 274 if (fl >= 0) 275 fcntl(sock->fd, F_SETFL, fl | O_NONBLOCK); 276 } 277 278 ret = register_poll(sock, flags); 279 if (ret < 0) 280 goto out; 281 282 if (uloop_fd_set_cb) 283 uloop_fd_set_cb(sock, flags); 284 285 sock->flags = flags; 286 sock->registered = true; 287 sock->eof = false; 288 sock->error = false; 289 290 out: 291 return ret; 292 } 293 294 int uloop_fd_delete(struct uloop_fd *fd) 295 { 296 int ret; 297 int i; 298 299 for (i = 0; i < cur_nfds; i++) { 300 if (cur_fds[cur_fd + i].fd != fd) 301 continue; 302 303 cur_fds[cur_fd + i].fd = NULL; 304 } 305 306 if (!fd->registered) 307 return 0; 308 309 if (uloop_fd_set_cb) 310 uloop_fd_set_cb(fd, 0); 311 312 fd->registered = false; 313 uloop_fd_stack_event(fd, -1); 314 ret = __uloop_fd_delete(fd); 315 fd->flags = 0; 316 317 return ret; 318 } 319 320 static int64_t tv_diff(struct timeval *t1, struct timeval *t2) 321 { 322 return 323 (t1->tv_sec - t2->tv_sec) * 1000 + 324 (t1->tv_usec - t2->tv_usec) / 1000; 325 } 326 327 int uloop_timeout_add(struct uloop_timeout *timeout) 328 { 329 struct uloop_timeout *tmp; 330 struct list_head *h = &timeouts; 331 332 if (timeout->pending) 333 return -1; 334 335 list_for_each_entry(tmp, &timeouts, list) { 336 if (tv_diff(&tmp->time, &timeout->time) > 0) { 337 h = &tmp->list; 338 break; 339 } 340 } 341 342 list_add_tail(&timeout->list, h); 343 timeout->pending = true; 344 345 return 0; 346 } 347 348 static void uloop_gettime(struct timeval *tv) 349 { 350 struct timespec ts; 351 352 clock_gettime(CLOCK_MONOTONIC, &ts); 353 tv->tv_sec = ts.tv_sec; 354 tv->tv_usec = ts.tv_nsec / 1000; 355 } 356 357 int uloop_timeout_set(struct uloop_timeout *timeout, int msecs) 358 { 359 struct timeval *time = &timeout->time; 360 361 if (timeout->pending) 362 uloop_timeout_cancel(timeout); 363 364 uloop_gettime(time); 365 366 time->tv_sec += msecs / 1000; 367 time->tv_usec += (msecs % 1000) * 1000; 368 369 if (time->tv_usec > 1000000) { 370 time->tv_sec++; 371 time->tv_usec -= 1000000; 372 } 373 374 return uloop_timeout_add(timeout); 375 } 376 377 int uloop_timeout_cancel(struct uloop_timeout *timeout) 378 { 379 if (!timeout->pending) 380 return -1; 381 382 list_del(&timeout->list); 383 timeout->pending = false; 384 385 return 0; 386 } 387 388 int uloop_timeout_remaining(struct uloop_timeout *timeout) 389 { 390 int64_t td; 391 struct timeval now; 392 393 if (!timeout->pending) 394 return -1; 395 396 uloop_gettime(&now); 397 398 td = tv_diff(&timeout->time, &now); 399 400 if (td > INT_MAX) 401 return INT_MAX; 402 else if (td < INT_MIN) 403 return INT_MIN; 404 else 405 return (int)td; 406 } 407 408 int64_t uloop_timeout_remaining64(struct uloop_timeout *timeout) 409 { 410 struct timeval now; 411 412 if (!timeout->pending) 413 return -1; 414 415 uloop_gettime(&now); 416 417 return tv_diff(&timeout->time, &now); 418 } 419 420 int uloop_process_add(struct uloop_process *p) 421 { 422 struct uloop_process *tmp; 423 struct list_head *h = &processes; 424 425 if (p->pending) 426 return -1; 427 428 list_for_each_entry(tmp, &processes, list) { 429 if (tmp->pid > p->pid) { 430 h = &tmp->list; 431 break; 432 } 433 } 434 435 list_add_tail(&p->list, h); 436 p->pending = true; 437 438 return 0; 439 } 440 441 static struct uloop_process *uloop_process_next_entry(struct uloop_process *p) 442 { 443 if (list_is_last(&p->list, &processes)) 444 return NULL; 445 446 return list_next_entry(p, list); 447 } 448 449 int uloop_process_delete(struct uloop_process *p) 450 { 451 if (!p->pending) 452 return -1; 453 454 if (process_next == p) 455 process_next = uloop_process_next_entry(p); 456 457 list_del(&p->list); 458 p->pending = false; 459 460 return 0; 461 } 462 463 static void uloop_handle_processes(void) 464 { 465 struct uloop_process *p; 466 pid_t pid; 467 int ret; 468 469 do_sigchld = 0; 470 471 while (1) { 472 pid = waitpid(-1, &ret, WNOHANG); 473 if (pid < 0 && errno == EINTR) 474 continue; 475 476 if (pid <= 0) 477 break; 478 479 process_next = list_empty(&processes) ? NULL : 480 list_first_entry(&processes, struct uloop_process, list); 481 482 while ((p = process_next) != NULL) { 483 process_next = uloop_process_next_entry(p); 484 485 if (p->pid < pid) 486 continue; 487 488 if (p->pid > pid) 489 break; 490 491 uloop_process_delete(p); 492 p->cb(p, ret); 493 } 494 } 495 496 process_next = NULL; 497 } 498 499 int uloop_interval_set(struct uloop_interval *timer, unsigned int msecs) 500 { 501 return timer_register(timer, msecs); 502 } 503 504 int uloop_interval_cancel(struct uloop_interval *timer) 505 { 506 return timer_remove(timer); 507 } 508 509 int64_t uloop_interval_remaining(struct uloop_interval *timer) 510 { 511 return timer_next(timer); 512 } 513 514 static void uloop_signal_wake(int signo) 515 { 516 uint8_t sigbyte = signo; 517 518 if (signo == SIGCHLD) 519 do_sigchld = 1; 520 521 do { 522 if (write(waker_pipe, &sigbyte, 1) < 0) { 523 if (errno == EINTR) 524 continue; 525 } 526 break; 527 } while (1); 528 } 529 530 static void uloop_handle_sigint(int signo) 531 { 532 uloop_status = signo; 533 uloop_cancelled = true; 534 uloop_signal_wake(signo); 535 } 536 537 static void uloop_install_handler(int signum, void (*handler)(int), struct sigaction* old, bool add) 538 { 539 struct sigaction s; 540 struct sigaction *act; 541 542 act = NULL; 543 sigaction(signum, NULL, &s); 544 545 if (add) { 546 if (s.sa_handler == SIG_DFL) { /* Do not override existing custom signal handlers */ 547 memcpy(old, &s, sizeof(struct sigaction)); 548 s.sa_handler = handler; 549 s.sa_flags = 0; 550 act = &s; 551 } 552 } 553 else if (s.sa_handler == handler) { /* Do not restore if someone modified our handler */ 554 act = old; 555 } 556 557 if (act != NULL) 558 sigaction(signum, act, NULL); 559 } 560 561 static void uloop_ignore_signal(int signum, bool ignore) 562 { 563 struct sigaction s; 564 void *new_handler = NULL; 565 566 sigaction(signum, NULL, &s); 567 568 if (ignore) { 569 if (s.sa_handler == SIG_DFL) /* Ignore only if there isn't any custom handler */ 570 new_handler = SIG_IGN; 571 } else { 572 if (s.sa_handler == SIG_IGN) /* Restore only if noone modified our SIG_IGN */ 573 new_handler = SIG_DFL; 574 } 575 576 if (new_handler) { 577 s.sa_handler = new_handler; 578 s.sa_flags = 0; 579 sigaction(signum, &s, NULL); 580 } 581 } 582 583 static void uloop_setup_signals(bool add) 584 { 585 static struct sigaction old_sigint, old_sigchld, old_sigterm; 586 587 uloop_install_handler(SIGINT, uloop_handle_sigint, &old_sigint, add); 588 uloop_install_handler(SIGTERM, uloop_handle_sigint, &old_sigterm, add); 589 590 if (uloop_handle_sigchld) 591 uloop_install_handler(SIGCHLD, uloop_signal_wake, &old_sigchld, add); 592 593 uloop_ignore_signal(SIGPIPE, add); 594 } 595 596 int uloop_signal_add(struct uloop_signal *s) 597 { 598 struct list_head *h = &signals; 599 struct uloop_signal *tmp; 600 struct sigaction sa; 601 602 if (s->pending) 603 return -1; 604 605 list_for_each_entry(tmp, &signals, list) { 606 if (tmp->signo > s->signo) { 607 h = &tmp->list; 608 break; 609 } 610 } 611 612 list_add_tail(&s->list, h); 613 s->pending = true; 614 615 sigaction(s->signo, NULL, &s->orig); 616 617 if (s->orig.sa_handler != uloop_signal_wake) { 618 sa.sa_handler = uloop_signal_wake; 619 sa.sa_flags = 0; 620 sigemptyset(&sa.sa_mask); 621 sigaction(s->signo, &sa, NULL); 622 } 623 624 return 0; 625 } 626 627 int uloop_signal_delete(struct uloop_signal *s) 628 { 629 struct uloop_signal *tmp; 630 631 if (!s->pending) 632 return -1; 633 634 if (signal_next == s) 635 signal_next = uloop_signal_next_entry(s); 636 637 list_del(&s->list); 638 s->pending = false; 639 640 /* Only the first watcher registered for a signal saved the real 641 * original disposition; later ones saved uloop_signal_wake. */ 642 if (s->orig.sa_handler == uloop_signal_wake) 643 return 0; 644 645 list_for_each_entry(tmp, &signals, list) { 646 if (tmp->signo != s->signo) 647 continue; 648 649 /* Other watchers remain for this signal, hand the saved 650 * disposition over to one of them so it can be restored once 651 * the last watcher is removed. */ 652 tmp->orig = s->orig; 653 return 0; 654 } 655 656 sigaction(s->signo, &s->orig, NULL); 657 658 return 0; 659 } 660 661 int uloop_get_next_timeout(void) 662 { 663 struct uloop_timeout *timeout; 664 struct timeval tv; 665 int64_t diff; 666 667 if (list_empty(&timeouts)) 668 return -1; 669 670 uloop_gettime(&tv); 671 672 timeout = list_first_entry(&timeouts, struct uloop_timeout, list); 673 diff = tv_diff(&timeout->time, &tv); 674 if (diff < 0) 675 return 0; 676 if (diff > INT_MAX) 677 return INT_MAX; 678 679 return diff; 680 } 681 682 static void uloop_process_timeouts(void) 683 { 684 struct uloop_timeout *t; 685 struct timeval tv; 686 687 if (list_empty(&timeouts)) 688 return; 689 690 uloop_gettime(&tv); 691 while (!list_empty(&timeouts)) { 692 t = list_first_entry(&timeouts, struct uloop_timeout, list); 693 694 if (tv_diff(&t->time, &tv) > 0) 695 break; 696 697 uloop_timeout_cancel(t); 698 if (t->cb) 699 t->cb(t); 700 } 701 } 702 703 static void uloop_clear_timeouts(void) 704 { 705 struct uloop_timeout *t, *tmp; 706 707 list_for_each_entry_safe(t, tmp, &timeouts, list) 708 uloop_timeout_cancel(t); 709 } 710 711 static void uloop_clear_processes(void) 712 { 713 struct uloop_process *p, *tmp; 714 715 list_for_each_entry_safe(p, tmp, &processes, list) 716 uloop_process_delete(p); 717 } 718 719 bool uloop_cancelling(void) 720 { 721 return uloop_run_depth > 0 && uloop_cancelled; 722 } 723 724 int uloop_run_timeout(int timeout) 725 { 726 int next_time = 0; 727 728 uloop_run_depth++; 729 730 uloop_status = 0; 731 uloop_cancelled = false; 732 do { 733 uloop_process_timeouts(); 734 735 if (do_sigchld) 736 uloop_handle_processes(); 737 738 if (uloop_cancelled) 739 break; 740 741 next_time = uloop_get_next_timeout(); 742 if (timeout >= 0 && (next_time < 0 || timeout < next_time)) 743 next_time = timeout; 744 uloop_run_events(next_time); 745 } while (!uloop_cancelled && timeout < 0); 746 747 --uloop_run_depth; 748 749 return uloop_status; 750 } 751 752 void uloop_done(void) 753 { 754 uloop_setup_signals(false); 755 756 if (poll_fd >= 0) { 757 close(poll_fd); 758 poll_fd = -1; 759 } 760 761 if (waker_pipe >= 0) { 762 uloop_fd_delete(&waker_fd); 763 close(waker_pipe); 764 close(waker_fd.fd); 765 waker_pipe = -1; 766 } 767 768 uloop_clear_timeouts(); 769 uloop_clear_processes(); 770 } 771
This page was automatically generated by LXR 0.3.1. • OpenWrt