Home | History | Annotate | Download | only in utils
      1 /*
      2  * Event loop based on select() loop
      3  * Copyright (c) 2002-2009, Jouni Malinen <j (at) 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 
     22 struct 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 
     32 struct 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 
     43 struct eloop_signal {
     44 	int sig;
     45 	void *user_data;
     46 	eloop_signal_handler handler;
     47 	int signaled;
     48 };
     49 
     50 struct eloop_sock_table {
     51 	int count;
     52 	struct eloop_sock *table;
     53 	int changed;
     54 };
     55 
     56 struct 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 
     81 static struct eloop_data eloop;
     82 
     83 
     84 #ifdef WPA_TRACE
     85 
     86 static void eloop_sigsegv_handler(int sig)
     87 {
     88 	wpa_trace_show("eloop SIGSEGV");
     89 	abort();
     90 }
     91 
     92 static 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 
    106 static 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 
    127 int 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 
    138 static 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(eloop.pollfds_map, sizeof(struct pollfd *) *
    157 				  (new_max_sock + 50));
    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(eloop.pollfds, sizeof(struct pollfd) * nmax);
    169 		if (n == NULL)
    170 			return -1;
    171 
    172 		eloop.max_poll_fds = nmax;
    173 		eloop.pollfds = n;
    174 	}
    175 #endif /* CONFIG_ELOOP_POLL */
    176 
    177 	eloop_trace_sock_remove_ref(table);
    178 	tmp = (struct eloop_sock *)
    179 		os_realloc(table->table,
    180 			   (table->count + 1) * 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 
    200 static 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 
    229 static 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 
    237 static 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 |= POLLIN;
    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 
    314 static 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 
    346 static 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))
    354 		return; /* pollfds may be invalid at this point */
    355 
    356 	if (eloop_sock_table_dispatch_table(writers, pollfds_map,
    357 					    max_pollfd_map, POLLOUT))
    358 		return; /* pollfds may be invalid at this point */
    359 
    360 	eloop_sock_table_dispatch_table(exceptions, pollfds_map,
    361 					max_pollfd_map, POLLERR | POLLHUP);
    362 }
    363 
    364 #else /* CONFIG_ELOOP_POLL */
    365 
    366 static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
    367 				     fd_set *fds)
    368 {
    369 	int i;
    370 
    371 	FD_ZERO(fds);
    372 
    373 	if (table->table == NULL)
    374 		return;
    375 
    376 	for (i = 0; i < table->count; i++)
    377 		FD_SET(table->table[i].sock, fds);
    378 }
    379 
    380 
    381 static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
    382 				      fd_set *fds)
    383 {
    384 	int i;
    385 
    386 	if (table == NULL || table->table == NULL)
    387 		return;
    388 
    389 	table->changed = 0;
    390 	for (i = 0; i < table->count; i++) {
    391 		if (FD_ISSET(table->table[i].sock, fds)) {
    392 			table->table[i].handler(table->table[i].sock,
    393 						table->table[i].eloop_data,
    394 						table->table[i].user_data);
    395 			if (table->changed)
    396 				break;
    397 		}
    398 	}
    399 }
    400 
    401 #endif /* CONFIG_ELOOP_POLL */
    402 
    403 
    404 static void eloop_sock_table_destroy(struct eloop_sock_table *table)
    405 {
    406 	if (table) {
    407 		int i;
    408 		for (i = 0; i < table->count && table->table; i++) {
    409 			wpa_printf(MSG_INFO, "ELOOP: remaining socket: "
    410 				   "sock=%d eloop_data=%p user_data=%p "
    411 				   "handler=%p",
    412 				   table->table[i].sock,
    413 				   table->table[i].eloop_data,
    414 				   table->table[i].user_data,
    415 				   table->table[i].handler);
    416 			wpa_trace_dump_funcname("eloop unregistered socket "
    417 						"handler",
    418 						table->table[i].handler);
    419 			wpa_trace_dump("eloop sock", &table->table[i]);
    420 		}
    421 		os_free(table->table);
    422 	}
    423 }
    424 
    425 
    426 int eloop_register_read_sock(int sock, eloop_sock_handler handler,
    427 			     void *eloop_data, void *user_data)
    428 {
    429 	return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
    430 				   eloop_data, user_data);
    431 }
    432 
    433 
    434 void eloop_unregister_read_sock(int sock)
    435 {
    436 	eloop_unregister_sock(sock, EVENT_TYPE_READ);
    437 }
    438 
    439 
    440 static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
    441 {
    442 	switch (type) {
    443 	case EVENT_TYPE_READ:
    444 		return &eloop.readers;
    445 	case EVENT_TYPE_WRITE:
    446 		return &eloop.writers;
    447 	case EVENT_TYPE_EXCEPTION:
    448 		return &eloop.exceptions;
    449 	}
    450 
    451 	return NULL;
    452 }
    453 
    454 
    455 int eloop_register_sock(int sock, eloop_event_type type,
    456 			eloop_sock_handler handler,
    457 			void *eloop_data, void *user_data)
    458 {
    459 	struct eloop_sock_table *table;
    460 
    461 	table = eloop_get_sock_table(type);
    462 	return eloop_sock_table_add_sock(table, sock, handler,
    463 					 eloop_data, user_data);
    464 }
    465 
    466 
    467 void eloop_unregister_sock(int sock, eloop_event_type type)
    468 {
    469 	struct eloop_sock_table *table;
    470 
    471 	table = eloop_get_sock_table(type);
    472 	eloop_sock_table_remove_sock(table, sock);
    473 }
    474 
    475 
    476 int eloop_register_timeout(unsigned int secs, unsigned int usecs,
    477 			   eloop_timeout_handler handler,
    478 			   void *eloop_data, void *user_data)
    479 {
    480 	struct eloop_timeout *timeout, *tmp;
    481 	os_time_t now_sec;
    482 
    483 	timeout = os_zalloc(sizeof(*timeout));
    484 	if (timeout == NULL)
    485 		return -1;
    486 	if (os_get_time(&timeout->time) < 0) {
    487 		os_free(timeout);
    488 		return -1;
    489 	}
    490 	now_sec = timeout->time.sec;
    491 	timeout->time.sec += secs;
    492 	if (timeout->time.sec < now_sec) {
    493 		/*
    494 		 * Integer overflow - assume long enough timeout to be assumed
    495 		 * to be infinite, i.e., the timeout would never happen.
    496 		 */
    497 		wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to "
    498 			   "ever happen - ignore it", secs);
    499 		os_free(timeout);
    500 		return 0;
    501 	}
    502 	timeout->time.usec += usecs;
    503 	while (timeout->time.usec >= 1000000) {
    504 		timeout->time.sec++;
    505 		timeout->time.usec -= 1000000;
    506 	}
    507 	timeout->eloop_data = eloop_data;
    508 	timeout->user_data = user_data;
    509 	timeout->handler = handler;
    510 	wpa_trace_add_ref(timeout, eloop, eloop_data);
    511 	wpa_trace_add_ref(timeout, user, user_data);
    512 	wpa_trace_record(timeout);
    513 
    514 	/* Maintain timeouts in order of increasing time */
    515 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
    516 		if (os_time_before(&timeout->time, &tmp->time)) {
    517 			dl_list_add(tmp->list.prev, &timeout->list);
    518 			return 0;
    519 		}
    520 	}
    521 	dl_list_add_tail(&eloop.timeout, &timeout->list);
    522 
    523 	return 0;
    524 }
    525 
    526 
    527 static void eloop_remove_timeout(struct eloop_timeout *timeout)
    528 {
    529 	dl_list_del(&timeout->list);
    530 	wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data);
    531 	wpa_trace_remove_ref(timeout, user, timeout->user_data);
    532 	os_free(timeout);
    533 }
    534 
    535 
    536 int eloop_cancel_timeout(eloop_timeout_handler handler,
    537 			 void *eloop_data, void *user_data)
    538 {
    539 	struct eloop_timeout *timeout, *prev;
    540 	int removed = 0;
    541 
    542 	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
    543 			      struct eloop_timeout, list) {
    544 		if (timeout->handler == handler &&
    545 		    (timeout->eloop_data == eloop_data ||
    546 		     eloop_data == ELOOP_ALL_CTX) &&
    547 		    (timeout->user_data == user_data ||
    548 		     user_data == ELOOP_ALL_CTX)) {
    549 			eloop_remove_timeout(timeout);
    550 			removed++;
    551 		}
    552 	}
    553 
    554 	return removed;
    555 }
    556 
    557 
    558 int eloop_is_timeout_registered(eloop_timeout_handler handler,
    559 				void *eloop_data, void *user_data)
    560 {
    561 	struct eloop_timeout *tmp;
    562 
    563 	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
    564 		if (tmp->handler == handler &&
    565 		    tmp->eloop_data == eloop_data &&
    566 		    tmp->user_data == user_data)
    567 			return 1;
    568 	}
    569 
    570 	return 0;
    571 }
    572 
    573 
    574 #ifndef CONFIG_NATIVE_WINDOWS
    575 static void eloop_handle_alarm(int sig)
    576 {
    577 	wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in "
    578 		   "two seconds. Looks like there\n"
    579 		   "is a bug that ends up in a busy loop that "
    580 		   "prevents clean shutdown.\n"
    581 		   "Killing program forcefully.\n");
    582 	exit(1);
    583 }
    584 #endif /* CONFIG_NATIVE_WINDOWS */
    585 
    586 
    587 static void eloop_handle_signal(int sig)
    588 {
    589 	int i;
    590 
    591 #ifndef CONFIG_NATIVE_WINDOWS
    592 	if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) {
    593 		/* Use SIGALRM to break out from potential busy loops that
    594 		 * would not allow the program to be killed. */
    595 		eloop.pending_terminate = 1;
    596 		signal(SIGALRM, eloop_handle_alarm);
    597 		alarm(2);
    598 	}
    599 #endif /* CONFIG_NATIVE_WINDOWS */
    600 
    601 	eloop.signaled++;
    602 	for (i = 0; i < eloop.signal_count; i++) {
    603 		if (eloop.signals[i].sig == sig) {
    604 			eloop.signals[i].signaled++;
    605 			break;
    606 		}
    607 	}
    608 }
    609 
    610 
    611 static void eloop_process_pending_signals(void)
    612 {
    613 	int i;
    614 
    615 	if (eloop.signaled == 0)
    616 		return;
    617 	eloop.signaled = 0;
    618 
    619 	if (eloop.pending_terminate) {
    620 #ifndef CONFIG_NATIVE_WINDOWS
    621 		alarm(0);
    622 #endif /* CONFIG_NATIVE_WINDOWS */
    623 		eloop.pending_terminate = 0;
    624 	}
    625 
    626 	for (i = 0; i < eloop.signal_count; i++) {
    627 		if (eloop.signals[i].signaled) {
    628 			eloop.signals[i].signaled = 0;
    629 			eloop.signals[i].handler(eloop.signals[i].sig,
    630 						 eloop.signals[i].user_data);
    631 		}
    632 	}
    633 }
    634 
    635 
    636 int eloop_register_signal(int sig, eloop_signal_handler handler,
    637 			  void *user_data)
    638 {
    639 	struct eloop_signal *tmp;
    640 
    641 	tmp = (struct eloop_signal *)
    642 		os_realloc(eloop.signals,
    643 			   (eloop.signal_count + 1) *
    644 			   sizeof(struct eloop_signal));
    645 	if (tmp == NULL)
    646 		return -1;
    647 
    648 	tmp[eloop.signal_count].sig = sig;
    649 	tmp[eloop.signal_count].user_data = user_data;
    650 	tmp[eloop.signal_count].handler = handler;
    651 	tmp[eloop.signal_count].signaled = 0;
    652 	eloop.signal_count++;
    653 	eloop.signals = tmp;
    654 	signal(sig, eloop_handle_signal);
    655 
    656 	return 0;
    657 }
    658 
    659 
    660 int eloop_register_signal_terminate(eloop_signal_handler handler,
    661 				    void *user_data)
    662 {
    663 	int ret = eloop_register_signal(SIGINT, handler, user_data);
    664 	if (ret == 0)
    665 		ret = eloop_register_signal(SIGTERM, handler, user_data);
    666 	return ret;
    667 }
    668 
    669 
    670 int eloop_register_signal_reconfig(eloop_signal_handler handler,
    671 				   void *user_data)
    672 {
    673 #ifdef CONFIG_NATIVE_WINDOWS
    674 	return 0;
    675 #else /* CONFIG_NATIVE_WINDOWS */
    676 	return eloop_register_signal(SIGHUP, handler, user_data);
    677 #endif /* CONFIG_NATIVE_WINDOWS */
    678 }
    679 
    680 
    681 void eloop_run(void)
    682 {
    683 #ifdef CONFIG_ELOOP_POLL
    684 	int num_poll_fds;
    685 	int timeout_ms = 0;
    686 #else /* CONFIG_ELOOP_POLL */
    687 	fd_set *rfds, *wfds, *efds;
    688 	struct timeval _tv;
    689 #endif /* CONFIG_ELOOP_POLL */
    690 	int res;
    691 	struct os_time tv, now;
    692 
    693 #ifndef CONFIG_ELOOP_POLL
    694 	rfds = os_malloc(sizeof(*rfds));
    695 	wfds = os_malloc(sizeof(*wfds));
    696 	efds = os_malloc(sizeof(*efds));
    697 	if (rfds == NULL || wfds == NULL || efds == NULL)
    698 		goto out;
    699 #endif /* CONFIG_ELOOP_POLL */
    700 
    701 	while (!eloop.terminate &&
    702 	       (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||
    703 		eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
    704 		struct eloop_timeout *timeout;
    705 		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
    706 					list);
    707 		if (timeout) {
    708 			os_get_time(&now);
    709 			if (os_time_before(&now, &timeout->time))
    710 				os_time_sub(&timeout->time, &now, &tv);
    711 			else
    712 				tv.sec = tv.usec = 0;
    713 #ifdef CONFIG_ELOOP_POLL
    714 			timeout_ms = tv.sec * 1000 + tv.usec / 1000;
    715 #else /* CONFIG_ELOOP_POLL */
    716 			_tv.tv_sec = tv.sec;
    717 			_tv.tv_usec = tv.usec;
    718 #endif /* CONFIG_ELOOP_POLL */
    719 		}
    720 
    721 #ifdef CONFIG_ELOOP_POLL
    722 		num_poll_fds = eloop_sock_table_set_fds(
    723 			&eloop.readers, &eloop.writers, &eloop.exceptions,
    724 			eloop.pollfds, eloop.pollfds_map,
    725 			eloop.max_pollfd_map);
    726 		res = poll(eloop.pollfds, num_poll_fds,
    727 			   timeout ? timeout_ms : -1);
    728 
    729 		if (res < 0 && errno != EINTR && errno != 0) {
    730 			perror("poll");
    731 			goto out;
    732 		}
    733 #else /* CONFIG_ELOOP_POLL */
    734 		eloop_sock_table_set_fds(&eloop.readers, rfds);
    735 		eloop_sock_table_set_fds(&eloop.writers, wfds);
    736 		eloop_sock_table_set_fds(&eloop.exceptions, efds);
    737 		res = select(eloop.max_sock + 1, rfds, wfds, efds,
    738 			     timeout ? &_tv : NULL);
    739 		if (res < 0 && errno != EINTR && errno != 0) {
    740 			perror("select");
    741 			goto out;
    742 		}
    743 #endif /* CONFIG_ELOOP_POLL */
    744 		eloop_process_pending_signals();
    745 
    746 		/* check if some registered timeouts have occurred */
    747 		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
    748 					list);
    749 		if (timeout) {
    750 			os_get_time(&now);
    751 			if (!os_time_before(&now, &timeout->time)) {
    752 				void *eloop_data = timeout->eloop_data;
    753 				void *user_data = timeout->user_data;
    754 				eloop_timeout_handler handler =
    755 					timeout->handler;
    756 				eloop_remove_timeout(timeout);
    757 				handler(eloop_data, user_data);
    758 			}
    759 
    760 		}
    761 
    762 		if (res <= 0)
    763 			continue;
    764 
    765 #ifdef CONFIG_ELOOP_POLL
    766 		eloop_sock_table_dispatch(&eloop.readers, &eloop.writers,
    767 					  &eloop.exceptions, eloop.pollfds_map,
    768 					  eloop.max_pollfd_map);
    769 #else /* CONFIG_ELOOP_POLL */
    770 		eloop_sock_table_dispatch(&eloop.readers, rfds);
    771 		eloop_sock_table_dispatch(&eloop.writers, wfds);
    772 		eloop_sock_table_dispatch(&eloop.exceptions, efds);
    773 #endif /* CONFIG_ELOOP_POLL */
    774 	}
    775 
    776 out:
    777 #ifndef CONFIG_ELOOP_POLL
    778 	os_free(rfds);
    779 	os_free(wfds);
    780 	os_free(efds);
    781 #endif /* CONFIG_ELOOP_POLL */
    782 	return;
    783 }
    784 
    785 
    786 void eloop_terminate(void)
    787 {
    788 	eloop.terminate = 1;
    789 }
    790 
    791 
    792 void eloop_destroy(void)
    793 {
    794 	struct eloop_timeout *timeout, *prev;
    795 	struct os_time now;
    796 
    797 	os_get_time(&now);
    798 	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
    799 			      struct eloop_timeout, list) {
    800 		int sec, usec;
    801 		sec = timeout->time.sec - now.sec;
    802 		usec = timeout->time.usec - now.usec;
    803 		if (timeout->time.usec < now.usec) {
    804 			sec--;
    805 			usec += 1000000;
    806 		}
    807 		wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d "
    808 			   "eloop_data=%p user_data=%p handler=%p",
    809 			   sec, usec, timeout->eloop_data, timeout->user_data,
    810 			   timeout->handler);
    811 		wpa_trace_dump_funcname("eloop unregistered timeout handler",
    812 					timeout->handler);
    813 		wpa_trace_dump("eloop timeout", timeout);
    814 		eloop_remove_timeout(timeout);
    815 	}
    816 	eloop_sock_table_destroy(&eloop.readers);
    817 	eloop_sock_table_destroy(&eloop.writers);
    818 	eloop_sock_table_destroy(&eloop.exceptions);
    819 	os_free(eloop.signals);
    820 
    821 #ifdef CONFIG_ELOOP_POLL
    822 	os_free(eloop.pollfds);
    823 	os_free(eloop.pollfds_map);
    824 #endif /* CONFIG_ELOOP_POLL */
    825 }
    826 
    827 
    828 int eloop_terminated(void)
    829 {
    830 	return eloop.terminate;
    831 }
    832 
    833 
    834 void eloop_wait_for_read_sock(int sock)
    835 {
    836 #ifdef CONFIG_ELOOP_POLL
    837 	struct pollfd pfd;
    838 
    839 	if (sock < 0)
    840 		return;
    841 
    842 	os_memset(&pfd, 0, sizeof(pfd));
    843 	pfd.fd = sock;
    844 	pfd.events = POLLIN;
    845 
    846 	poll(&pfd, 1, -1);
    847 #else /* CONFIG_ELOOP_POLL */
    848 	fd_set rfds;
    849 
    850 	if (sock < 0)
    851 		return;
    852 
    853 	FD_ZERO(&rfds);
    854 	FD_SET(sock, &rfds);
    855 	select(sock + 1, &rfds, NULL, NULL, NULL);
    856 #endif /* CONFIG_ELOOP_POLL */
    857 }
    858