1/* 2 * Event loop based on select() loop 3 * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9#include "includes.h" 10 11#include "common.h" 12#include "trace.h" 13#include "list.h" 14#include "eloop.h" 15 16#ifdef CONFIG_ELOOP_POLL 17#include <assert.h> 18#include <poll.h> 19#endif /* CONFIG_ELOOP_POLL */ 20 21 22struct eloop_sock { 23 int sock; 24 void *eloop_data; 25 void *user_data; 26 eloop_sock_handler handler; 27 WPA_TRACE_REF(eloop); 28 WPA_TRACE_REF(user); 29 WPA_TRACE_INFO 30}; 31 32struct eloop_timeout { 33 struct dl_list list; 34 struct os_time time; 35 void *eloop_data; 36 void *user_data; 37 eloop_timeout_handler handler; 38 WPA_TRACE_REF(eloop); 39 WPA_TRACE_REF(user); 40 WPA_TRACE_INFO 41}; 42 43struct eloop_signal { 44 int sig; 45 void *user_data; 46 eloop_signal_handler handler; 47 int signaled; 48}; 49 50struct eloop_sock_table { 51 int count; 52 struct eloop_sock *table; 53 int changed; 54}; 55 56struct eloop_data { 57 int max_sock; 58 59 int count; /* sum of all table counts */ 60#ifdef CONFIG_ELOOP_POLL 61 int max_pollfd_map; /* number of pollfds_map currently allocated */ 62 int max_poll_fds; /* number of pollfds currently allocated */ 63 struct pollfd *pollfds; 64 struct pollfd **pollfds_map; 65#endif /* CONFIG_ELOOP_POLL */ 66 struct eloop_sock_table readers; 67 struct eloop_sock_table writers; 68 struct eloop_sock_table exceptions; 69 70 struct dl_list timeout; 71 72 int signal_count; 73 struct eloop_signal *signals; 74 int signaled; 75 int pending_terminate; 76 77 int terminate; 78 int reader_table_changed; 79}; 80 81static struct eloop_data eloop; 82 83 84#ifdef WPA_TRACE 85 86static void eloop_sigsegv_handler(int sig) 87{ 88 wpa_trace_show("eloop SIGSEGV"); 89 abort(); 90} 91 92static void eloop_trace_sock_add_ref(struct eloop_sock_table *table) 93{ 94 int i; 95 if (table == NULL || table->table == NULL) 96 return; 97 for (i = 0; i < table->count; i++) { 98 wpa_trace_add_ref(&table->table[i], eloop, 99 table->table[i].eloop_data); 100 wpa_trace_add_ref(&table->table[i], user, 101 table->table[i].user_data); 102 } 103} 104 105 106static void eloop_trace_sock_remove_ref(struct eloop_sock_table *table) 107{ 108 int i; 109 if (table == NULL || table->table == NULL) 110 return; 111 for (i = 0; i < table->count; i++) { 112 wpa_trace_remove_ref(&table->table[i], eloop, 113 table->table[i].eloop_data); 114 wpa_trace_remove_ref(&table->table[i], user, 115 table->table[i].user_data); 116 } 117} 118 119#else /* WPA_TRACE */ 120 121#define eloop_trace_sock_add_ref(table) do { } while (0) 122#define eloop_trace_sock_remove_ref(table) do { } while (0) 123 124#endif /* WPA_TRACE */ 125 126 127int eloop_init(void) 128{ 129 os_memset(&eloop, 0, sizeof(eloop)); 130 dl_list_init(&eloop.timeout); 131#ifdef WPA_TRACE 132 signal(SIGSEGV, eloop_sigsegv_handler); 133#endif /* WPA_TRACE */ 134 return 0; 135} 136 137 138static int eloop_sock_table_add_sock(struct eloop_sock_table *table, 139 int sock, eloop_sock_handler handler, 140 void *eloop_data, void *user_data) 141{ 142 struct eloop_sock *tmp; 143 int new_max_sock; 144 145 if (sock > eloop.max_sock) 146 new_max_sock = sock; 147 else 148 new_max_sock = eloop.max_sock; 149 150 if (table == NULL) 151 return -1; 152 153#ifdef CONFIG_ELOOP_POLL 154 if (new_max_sock >= eloop.max_pollfd_map) { 155 struct pollfd **nmap; 156 nmap = os_realloc_array(eloop.pollfds_map, new_max_sock + 50, 157 sizeof(struct pollfd *)); 158 if (nmap == NULL) 159 return -1; 160 161 eloop.max_pollfd_map = new_max_sock + 50; 162 eloop.pollfds_map = nmap; 163 } 164 165 if (eloop.count + 1 > eloop.max_poll_fds) { 166 struct pollfd *n; 167 int nmax = eloop.count + 1 + 50; 168 n = os_realloc_array(eloop.pollfds, nmax, 169 sizeof(struct pollfd)); 170 if (n == NULL) 171 return -1; 172 173 eloop.max_poll_fds = nmax; 174 eloop.pollfds = n; 175 } 176#endif /* CONFIG_ELOOP_POLL */ 177 178 eloop_trace_sock_remove_ref(table); 179 tmp = os_realloc_array(table->table, table->count + 1, 180 sizeof(struct eloop_sock)); 181 if (tmp == NULL) 182 return -1; 183 184 tmp[table->count].sock = sock; 185 tmp[table->count].eloop_data = eloop_data; 186 tmp[table->count].user_data = user_data; 187 tmp[table->count].handler = handler; 188 wpa_trace_record(&tmp[table->count]); 189 table->count++; 190 table->table = tmp; 191 eloop.max_sock = new_max_sock; 192 eloop.count++; 193 table->changed = 1; 194 eloop_trace_sock_add_ref(table); 195 196 return 0; 197} 198 199 200static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, 201 int sock) 202{ 203 int i; 204 205 if (table == NULL || table->table == NULL || table->count == 0) 206 return; 207 208 for (i = 0; i < table->count; i++) { 209 if (table->table[i].sock == sock) 210 break; 211 } 212 if (i == table->count) 213 return; 214 eloop_trace_sock_remove_ref(table); 215 if (i != table->count - 1) { 216 os_memmove(&table->table[i], &table->table[i + 1], 217 (table->count - i - 1) * 218 sizeof(struct eloop_sock)); 219 } 220 table->count--; 221 eloop.count--; 222 table->changed = 1; 223 eloop_trace_sock_add_ref(table); 224} 225 226 227#ifdef CONFIG_ELOOP_POLL 228 229static struct pollfd * find_pollfd(struct pollfd **pollfds_map, int fd, int mx) 230{ 231 if (fd < mx && fd >= 0) 232 return pollfds_map[fd]; 233 return NULL; 234} 235 236 237static int eloop_sock_table_set_fds(struct eloop_sock_table *readers, 238 struct eloop_sock_table *writers, 239 struct eloop_sock_table *exceptions, 240 struct pollfd *pollfds, 241 struct pollfd **pollfds_map, 242 int max_pollfd_map) 243{ 244 int i; 245 int nxt = 0; 246 int fd; 247 struct pollfd *pfd; 248 249 /* Clear pollfd lookup map. It will be re-populated below. */ 250 os_memset(pollfds_map, 0, sizeof(struct pollfd *) * max_pollfd_map); 251 252 if (readers && readers->table) { 253 for (i = 0; i < readers->count; i++) { 254 fd = readers->table[i].sock; 255 assert(fd >= 0 && fd < max_pollfd_map); 256 pollfds[nxt].fd = fd; 257 pollfds[nxt].events = POLLIN; 258 pollfds[nxt].revents = 0; 259 pollfds_map[fd] = &(pollfds[nxt]); 260 nxt++; 261 } 262 } 263 264 if (writers && writers->table) { 265 for (i = 0; i < writers->count; i++) { 266 /* 267 * See if we already added this descriptor, update it 268 * if so. 269 */ 270 fd = writers->table[i].sock; 271 assert(fd >= 0 && fd < max_pollfd_map); 272 pfd = pollfds_map[fd]; 273 if (!pfd) { 274 pfd = &(pollfds[nxt]); 275 pfd->events = 0; 276 pfd->fd = fd; 277 pollfds[i].revents = 0; 278 pollfds_map[fd] = pfd; 279 nxt++; 280 } 281 pfd->events |= POLLOUT; 282 } 283 } 284 285 /* 286 * Exceptions are always checked when using poll, but I suppose it's 287 * possible that someone registered a socket *only* for exception 288 * handling. Set the POLLIN bit in this case. 289 */ 290 if (exceptions && exceptions->table) { 291 for (i = 0; i < exceptions->count; i++) { 292 /* 293 * See if we already added this descriptor, just use it 294 * if so. 295 */ 296 fd = exceptions->table[i].sock; 297 assert(fd >= 0 && fd < max_pollfd_map); 298 pfd = pollfds_map[fd]; 299 if (!pfd) { 300 pfd = &(pollfds[nxt]); 301 pfd->events = POLLIN; 302 pfd->fd = fd; 303 pollfds[i].revents = 0; 304 pollfds_map[fd] = pfd; 305 nxt++; 306 } 307 } 308 } 309 310 return nxt; 311} 312 313 314static int eloop_sock_table_dispatch_table(struct eloop_sock_table *table, 315 struct pollfd **pollfds_map, 316 int max_pollfd_map, 317 short int revents) 318{ 319 int i; 320 struct pollfd *pfd; 321 322 if (!table || !table->table) 323 return 0; 324 325 table->changed = 0; 326 for (i = 0; i < table->count; i++) { 327 pfd = find_pollfd(pollfds_map, table->table[i].sock, 328 max_pollfd_map); 329 if (!pfd) 330 continue; 331 332 if (!(pfd->revents & revents)) 333 continue; 334 335 table->table[i].handler(table->table[i].sock, 336 table->table[i].eloop_data, 337 table->table[i].user_data); 338 if (table->changed) 339 return 1; 340 } 341 342 return 0; 343} 344 345 346static void eloop_sock_table_dispatch(struct eloop_sock_table *readers, 347 struct eloop_sock_table *writers, 348 struct eloop_sock_table *exceptions, 349 struct pollfd **pollfds_map, 350 int max_pollfd_map) 351{ 352 if (eloop_sock_table_dispatch_table(readers, pollfds_map, 353 max_pollfd_map, POLLIN | POLLERR | 354 POLLHUP)) 355 return; /* pollfds may be invalid at this point */ 356 357 if (eloop_sock_table_dispatch_table(writers, pollfds_map, 358 max_pollfd_map, POLLOUT)) 359 return; /* pollfds may be invalid at this point */ 360 361 eloop_sock_table_dispatch_table(exceptions, pollfds_map, 362 max_pollfd_map, POLLERR | POLLHUP); 363} 364 365#else /* CONFIG_ELOOP_POLL */ 366 367static void eloop_sock_table_set_fds(struct eloop_sock_table *table, 368 fd_set *fds) 369{ 370 int i; 371 372 FD_ZERO(fds); 373 374 if (table->table == NULL) 375 return; 376 377 for (i = 0; i < table->count; i++) 378 FD_SET(table->table[i].sock, fds); 379} 380 381 382static void eloop_sock_table_dispatch(struct eloop_sock_table *table, 383 fd_set *fds) 384{ 385 int i; 386 387 if (table == NULL || table->table == NULL) 388 return; 389 390 table->changed = 0; 391 for (i = 0; i < table->count; i++) { 392 if (FD_ISSET(table->table[i].sock, fds)) { 393 table->table[i].handler(table->table[i].sock, 394 table->table[i].eloop_data, 395 table->table[i].user_data); 396 if (table->changed) 397 break; 398 } 399 } 400} 401 402#endif /* CONFIG_ELOOP_POLL */ 403 404 405static void eloop_sock_table_destroy(struct eloop_sock_table *table) 406{ 407 if (table) { 408 int i; 409 for (i = 0; i < table->count && table->table; i++) { 410 wpa_printf(MSG_INFO, "ELOOP: remaining socket: " 411 "sock=%d eloop_data=%p user_data=%p " 412 "handler=%p", 413 table->table[i].sock, 414 table->table[i].eloop_data, 415 table->table[i].user_data, 416 table->table[i].handler); 417 wpa_trace_dump_funcname("eloop unregistered socket " 418 "handler", 419 table->table[i].handler); 420 wpa_trace_dump("eloop sock", &table->table[i]); 421 } 422 os_free(table->table); 423 } 424} 425 426 427int eloop_register_read_sock(int sock, eloop_sock_handler handler, 428 void *eloop_data, void *user_data) 429{ 430 return eloop_register_sock(sock, EVENT_TYPE_READ, handler, 431 eloop_data, user_data); 432} 433 434 435void eloop_unregister_read_sock(int sock) 436{ 437 eloop_unregister_sock(sock, EVENT_TYPE_READ); 438} 439 440 441static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type) 442{ 443 switch (type) { 444 case EVENT_TYPE_READ: 445 return &eloop.readers; 446 case EVENT_TYPE_WRITE: 447 return &eloop.writers; 448 case EVENT_TYPE_EXCEPTION: 449 return &eloop.exceptions; 450 } 451 452 return NULL; 453} 454 455 456int eloop_register_sock(int sock, eloop_event_type type, 457 eloop_sock_handler handler, 458 void *eloop_data, void *user_data) 459{ 460 struct eloop_sock_table *table; 461 462 table = eloop_get_sock_table(type); 463 return eloop_sock_table_add_sock(table, sock, handler, 464 eloop_data, user_data); 465} 466 467 468void eloop_unregister_sock(int sock, eloop_event_type type) 469{ 470 struct eloop_sock_table *table; 471 472 table = eloop_get_sock_table(type); 473 eloop_sock_table_remove_sock(table, sock); 474} 475 476 477int eloop_register_timeout(unsigned int secs, unsigned int usecs, 478 eloop_timeout_handler handler, 479 void *eloop_data, void *user_data) 480{ 481 struct eloop_timeout *timeout, *tmp; 482 os_time_t now_sec; 483 484 timeout = os_zalloc(sizeof(*timeout)); 485 if (timeout == NULL) 486 return -1; 487 if (os_get_time(&timeout->time) < 0) { 488 os_free(timeout); 489 return -1; 490 } 491 now_sec = timeout->time.sec; 492 timeout->time.sec += secs; 493 if (timeout->time.sec < now_sec) { 494 /* 495 * Integer overflow - assume long enough timeout to be assumed 496 * to be infinite, i.e., the timeout would never happen. 497 */ 498 wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to " 499 "ever happen - ignore it", secs); 500 os_free(timeout); 501 return 0; 502 } 503 timeout->time.usec += usecs; 504 while (timeout->time.usec >= 1000000) { 505 timeout->time.sec++; 506 timeout->time.usec -= 1000000; 507 } 508 timeout->eloop_data = eloop_data; 509 timeout->user_data = user_data; 510 timeout->handler = handler; 511 wpa_trace_add_ref(timeout, eloop, eloop_data); 512 wpa_trace_add_ref(timeout, user, user_data); 513 wpa_trace_record(timeout); 514 515 /* Maintain timeouts in order of increasing time */ 516 dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 517 if (os_time_before(&timeout->time, &tmp->time)) { 518 dl_list_add(tmp->list.prev, &timeout->list); 519 return 0; 520 } 521 } 522 dl_list_add_tail(&eloop.timeout, &timeout->list); 523 524 return 0; 525} 526 527 528static void eloop_remove_timeout(struct eloop_timeout *timeout) 529{ 530 dl_list_del(&timeout->list); 531 wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data); 532 wpa_trace_remove_ref(timeout, user, timeout->user_data); 533 os_free(timeout); 534} 535 536 537int eloop_cancel_timeout(eloop_timeout_handler handler, 538 void *eloop_data, void *user_data) 539{ 540 struct eloop_timeout *timeout, *prev; 541 int removed = 0; 542 543 dl_list_for_each_safe(timeout, prev, &eloop.timeout, 544 struct eloop_timeout, list) { 545 if (timeout->handler == handler && 546 (timeout->eloop_data == eloop_data || 547 eloop_data == ELOOP_ALL_CTX) && 548 (timeout->user_data == user_data || 549 user_data == ELOOP_ALL_CTX)) { 550 eloop_remove_timeout(timeout); 551 removed++; 552 } 553 } 554 555 return removed; 556} 557 558 559int eloop_cancel_timeout_one(eloop_timeout_handler handler, 560 void *eloop_data, void *user_data, 561 struct os_time *remaining) 562{ 563 struct eloop_timeout *timeout, *prev; 564 int removed = 0; 565 struct os_time now; 566 567 os_get_time(&now); 568 remaining->sec = remaining->usec = 0; 569 570 dl_list_for_each_safe(timeout, prev, &eloop.timeout, 571 struct eloop_timeout, list) { 572 if (timeout->handler == handler && 573 (timeout->eloop_data == eloop_data) && 574 (timeout->user_data == user_data)) { 575 removed = 1; 576 if (os_time_before(&now, &timeout->time)) 577 os_time_sub(&timeout->time, &now, remaining); 578 eloop_remove_timeout(timeout); 579 break; 580 } 581 } 582 return removed; 583} 584 585 586int eloop_is_timeout_registered(eloop_timeout_handler handler, 587 void *eloop_data, void *user_data) 588{ 589 struct eloop_timeout *tmp; 590 591 dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { 592 if (tmp->handler == handler && 593 tmp->eloop_data == eloop_data && 594 tmp->user_data == user_data) 595 return 1; 596 } 597 598 return 0; 599} 600 601 602#ifndef CONFIG_NATIVE_WINDOWS 603static void eloop_handle_alarm(int sig) 604{ 605 wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in " 606 "two seconds. Looks like there\n" 607 "is a bug that ends up in a busy loop that " 608 "prevents clean shutdown.\n" 609 "Killing program forcefully.\n"); 610 exit(1); 611} 612#endif /* CONFIG_NATIVE_WINDOWS */ 613 614 615static void eloop_handle_signal(int sig) 616{ 617 int i; 618 619#ifndef CONFIG_NATIVE_WINDOWS 620 if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) { 621 /* Use SIGALRM to break out from potential busy loops that 622 * would not allow the program to be killed. */ 623 eloop.pending_terminate = 1; 624 signal(SIGALRM, eloop_handle_alarm); 625 alarm(2); 626 } 627#endif /* CONFIG_NATIVE_WINDOWS */ 628 629 eloop.signaled++; 630 for (i = 0; i < eloop.signal_count; i++) { 631 if (eloop.signals[i].sig == sig) { 632 eloop.signals[i].signaled++; 633 break; 634 } 635 } 636} 637 638 639static void eloop_process_pending_signals(void) 640{ 641 int i; 642 643 if (eloop.signaled == 0) 644 return; 645 eloop.signaled = 0; 646 647 if (eloop.pending_terminate) { 648#ifndef CONFIG_NATIVE_WINDOWS 649 alarm(0); 650#endif /* CONFIG_NATIVE_WINDOWS */ 651 eloop.pending_terminate = 0; 652 } 653 654 for (i = 0; i < eloop.signal_count; i++) { 655 if (eloop.signals[i].signaled) { 656 eloop.signals[i].signaled = 0; 657 eloop.signals[i].handler(eloop.signals[i].sig, 658 eloop.signals[i].user_data); 659 } 660 } 661} 662 663 664int eloop_register_signal(int sig, eloop_signal_handler handler, 665 void *user_data) 666{ 667 struct eloop_signal *tmp; 668 669 tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1, 670 sizeof(struct eloop_signal)); 671 if (tmp == NULL) 672 return -1; 673 674 tmp[eloop.signal_count].sig = sig; 675 tmp[eloop.signal_count].user_data = user_data; 676 tmp[eloop.signal_count].handler = handler; 677 tmp[eloop.signal_count].signaled = 0; 678 eloop.signal_count++; 679 eloop.signals = tmp; 680 signal(sig, eloop_handle_signal); 681 682 return 0; 683} 684 685 686int eloop_register_signal_terminate(eloop_signal_handler handler, 687 void *user_data) 688{ 689 int ret = eloop_register_signal(SIGINT, handler, user_data); 690 if (ret == 0) 691 ret = eloop_register_signal(SIGTERM, handler, user_data); 692 return ret; 693} 694 695 696int eloop_register_signal_reconfig(eloop_signal_handler handler, 697 void *user_data) 698{ 699#ifdef CONFIG_NATIVE_WINDOWS 700 return 0; 701#else /* CONFIG_NATIVE_WINDOWS */ 702 return eloop_register_signal(SIGHUP, handler, user_data); 703#endif /* CONFIG_NATIVE_WINDOWS */ 704} 705 706 707void eloop_run(void) 708{ 709#ifdef CONFIG_ELOOP_POLL 710 int num_poll_fds; 711 int timeout_ms = 0; 712#else /* CONFIG_ELOOP_POLL */ 713 fd_set *rfds, *wfds, *efds; 714 struct timeval _tv; 715#endif /* CONFIG_ELOOP_POLL */ 716 int res; 717 struct os_time tv, now; 718 719#ifndef CONFIG_ELOOP_POLL 720 rfds = os_malloc(sizeof(*rfds)); 721 wfds = os_malloc(sizeof(*wfds)); 722 efds = os_malloc(sizeof(*efds)); 723 if (rfds == NULL || wfds == NULL || efds == NULL) 724 goto out; 725#endif /* CONFIG_ELOOP_POLL */ 726 727 while (!eloop.terminate && 728 (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 || 729 eloop.writers.count > 0 || eloop.exceptions.count > 0)) { 730 struct eloop_timeout *timeout; 731 timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, 732 list); 733 if (timeout) { 734 os_get_time(&now); 735 if (os_time_before(&now, &timeout->time)) 736 os_time_sub(&timeout->time, &now, &tv); 737 else 738 tv.sec = tv.usec = 0; 739#ifdef CONFIG_ELOOP_POLL 740 timeout_ms = tv.sec * 1000 + tv.usec / 1000; 741#else /* CONFIG_ELOOP_POLL */ 742 _tv.tv_sec = tv.sec; 743 _tv.tv_usec = tv.usec; 744#endif /* CONFIG_ELOOP_POLL */ 745 } 746 747#ifdef CONFIG_ELOOP_POLL 748 num_poll_fds = eloop_sock_table_set_fds( 749 &eloop.readers, &eloop.writers, &eloop.exceptions, 750 eloop.pollfds, eloop.pollfds_map, 751 eloop.max_pollfd_map); 752 res = poll(eloop.pollfds, num_poll_fds, 753 timeout ? timeout_ms : -1); 754 755 if (res < 0 && errno != EINTR && errno != 0) { 756 perror("poll"); 757 goto out; 758 } 759#else /* CONFIG_ELOOP_POLL */ 760 eloop_sock_table_set_fds(&eloop.readers, rfds); 761 eloop_sock_table_set_fds(&eloop.writers, wfds); 762 eloop_sock_table_set_fds(&eloop.exceptions, efds); 763 res = select(eloop.max_sock + 1, rfds, wfds, efds, 764 timeout ? &_tv : NULL); 765 if (res < 0 && errno != EINTR && errno != 0) { 766 perror("select"); 767 goto out; 768 } 769#endif /* CONFIG_ELOOP_POLL */ 770 eloop_process_pending_signals(); 771 772 /* check if some registered timeouts have occurred */ 773 timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, 774 list); 775 if (timeout) { 776 os_get_time(&now); 777 if (!os_time_before(&now, &timeout->time)) { 778 void *eloop_data = timeout->eloop_data; 779 void *user_data = timeout->user_data; 780 eloop_timeout_handler handler = 781 timeout->handler; 782 eloop_remove_timeout(timeout); 783 handler(eloop_data, user_data); 784 } 785 786 } 787 788 if (res <= 0) 789 continue; 790 791#ifdef CONFIG_ELOOP_POLL 792 eloop_sock_table_dispatch(&eloop.readers, &eloop.writers, 793 &eloop.exceptions, eloop.pollfds_map, 794 eloop.max_pollfd_map); 795#else /* CONFIG_ELOOP_POLL */ 796 eloop_sock_table_dispatch(&eloop.readers, rfds); 797 eloop_sock_table_dispatch(&eloop.writers, wfds); 798 eloop_sock_table_dispatch(&eloop.exceptions, efds); 799#endif /* CONFIG_ELOOP_POLL */ 800 } 801 802 eloop.terminate = 0; 803out: 804#ifndef CONFIG_ELOOP_POLL 805 os_free(rfds); 806 os_free(wfds); 807 os_free(efds); 808#endif /* CONFIG_ELOOP_POLL */ 809 return; 810} 811 812 813void eloop_terminate(void) 814{ 815 eloop.terminate = 1; 816} 817 818 819void eloop_destroy(void) 820{ 821 struct eloop_timeout *timeout, *prev; 822 struct os_time now; 823 824 os_get_time(&now); 825 dl_list_for_each_safe(timeout, prev, &eloop.timeout, 826 struct eloop_timeout, list) { 827 int sec, usec; 828 sec = timeout->time.sec - now.sec; 829 usec = timeout->time.usec - now.usec; 830 if (timeout->time.usec < now.usec) { 831 sec--; 832 usec += 1000000; 833 } 834 wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d " 835 "eloop_data=%p user_data=%p handler=%p", 836 sec, usec, timeout->eloop_data, timeout->user_data, 837 timeout->handler); 838 wpa_trace_dump_funcname("eloop unregistered timeout handler", 839 timeout->handler); 840 wpa_trace_dump("eloop timeout", timeout); 841 eloop_remove_timeout(timeout); 842 } 843 eloop_sock_table_destroy(&eloop.readers); 844 eloop_sock_table_destroy(&eloop.writers); 845 eloop_sock_table_destroy(&eloop.exceptions); 846 os_free(eloop.signals); 847 848#ifdef CONFIG_ELOOP_POLL 849 os_free(eloop.pollfds); 850 os_free(eloop.pollfds_map); 851#endif /* CONFIG_ELOOP_POLL */ 852} 853 854 855int eloop_terminated(void) 856{ 857 return eloop.terminate; 858} 859 860 861void eloop_wait_for_read_sock(int sock) 862{ 863#ifdef CONFIG_ELOOP_POLL 864 struct pollfd pfd; 865 866 if (sock < 0) 867 return; 868 869 os_memset(&pfd, 0, sizeof(pfd)); 870 pfd.fd = sock; 871 pfd.events = POLLIN; 872 873 poll(&pfd, 1, -1); 874#else /* CONFIG_ELOOP_POLL */ 875 fd_set rfds; 876 877 if (sock < 0) 878 return; 879 880 FD_ZERO(&rfds); 881 FD_SET(sock, &rfds); 882 select(sock + 1, &rfds, NULL, NULL, NULL); 883#endif /* CONFIG_ELOOP_POLL */ 884} 885