Line data Source code
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 : #include <assert.h>
11 :
12 : #include "common.h"
13 : #include "trace.h"
14 : #include "list.h"
15 : #include "eloop.h"
16 :
17 : #if defined(CONFIG_ELOOP_POLL) && defined(CONFIG_ELOOP_EPOLL)
18 : #error Do not define both of poll and epoll
19 : #endif
20 :
21 : #if !defined(CONFIG_ELOOP_POLL) && !defined(CONFIG_ELOOP_EPOLL)
22 : #define CONFIG_ELOOP_SELECT
23 : #endif
24 :
25 : #ifdef CONFIG_ELOOP_POLL
26 : #include <poll.h>
27 : #endif /* CONFIG_ELOOP_POLL */
28 :
29 : #ifdef CONFIG_ELOOP_EPOLL
30 : #include <sys/epoll.h>
31 : #endif /* CONFIG_ELOOP_EPOLL */
32 :
33 : struct eloop_sock {
34 : int sock;
35 : void *eloop_data;
36 : void *user_data;
37 : eloop_sock_handler handler;
38 : WPA_TRACE_REF(eloop);
39 : WPA_TRACE_REF(user);
40 : WPA_TRACE_INFO
41 : };
42 :
43 : struct eloop_timeout {
44 : struct dl_list list;
45 : struct os_reltime time;
46 : void *eloop_data;
47 : void *user_data;
48 : eloop_timeout_handler handler;
49 : WPA_TRACE_REF(eloop);
50 : WPA_TRACE_REF(user);
51 : WPA_TRACE_INFO
52 : };
53 :
54 : struct eloop_signal {
55 : int sig;
56 : void *user_data;
57 : eloop_signal_handler handler;
58 : int signaled;
59 : };
60 :
61 : struct eloop_sock_table {
62 : int count;
63 : struct eloop_sock *table;
64 : eloop_event_type type;
65 : int changed;
66 : };
67 :
68 : struct eloop_data {
69 : int max_sock;
70 :
71 : int count; /* sum of all table counts */
72 : #ifdef CONFIG_ELOOP_POLL
73 : int max_pollfd_map; /* number of pollfds_map currently allocated */
74 : int max_poll_fds; /* number of pollfds currently allocated */
75 : struct pollfd *pollfds;
76 : struct pollfd **pollfds_map;
77 : #endif /* CONFIG_ELOOP_POLL */
78 : #ifdef CONFIG_ELOOP_EPOLL
79 : int epollfd;
80 : int epoll_max_event_num;
81 : int epoll_max_fd;
82 : struct eloop_sock *epoll_table;
83 : struct epoll_event *epoll_events;
84 : #endif /* CONFIG_ELOOP_EPOLL */
85 : struct eloop_sock_table readers;
86 : struct eloop_sock_table writers;
87 : struct eloop_sock_table exceptions;
88 :
89 : struct dl_list timeout;
90 :
91 : int signal_count;
92 : struct eloop_signal *signals;
93 : int signaled;
94 : int pending_terminate;
95 :
96 : int terminate;
97 : };
98 :
99 : static struct eloop_data eloop;
100 :
101 :
102 : #ifdef WPA_TRACE
103 :
104 0 : static void eloop_sigsegv_handler(int sig)
105 : {
106 0 : wpa_trace_show("eloop SIGSEGV");
107 0 : abort();
108 : }
109 :
110 47497 : static void eloop_trace_sock_add_ref(struct eloop_sock_table *table)
111 : {
112 : int i;
113 47497 : if (table == NULL || table->table == NULL)
114 47497 : return;
115 649649 : for (i = 0; i < table->count; i++) {
116 602152 : wpa_trace_add_ref(&table->table[i], eloop,
117 : table->table[i].eloop_data);
118 602152 : wpa_trace_add_ref(&table->table[i], user,
119 : table->table[i].user_data);
120 : }
121 : }
122 :
123 :
124 47497 : static void eloop_trace_sock_remove_ref(struct eloop_sock_table *table)
125 : {
126 : int i;
127 47497 : if (table == NULL || table->table == NULL)
128 47569 : return;
129 649577 : for (i = 0; i < table->count; i++) {
130 602152 : wpa_trace_remove_ref(&table->table[i], eloop,
131 : table->table[i].eloop_data);
132 602152 : wpa_trace_remove_ref(&table->table[i], user,
133 : table->table[i].user_data);
134 : }
135 : }
136 :
137 : #else /* WPA_TRACE */
138 :
139 : #define eloop_trace_sock_add_ref(table) do { } while (0)
140 : #define eloop_trace_sock_remove_ref(table) do { } while (0)
141 :
142 : #endif /* WPA_TRACE */
143 :
144 :
145 105 : int eloop_init(void)
146 : {
147 105 : os_memset(&eloop, 0, sizeof(eloop));
148 105 : dl_list_init(&eloop.timeout);
149 : #ifdef CONFIG_ELOOP_EPOLL
150 : eloop.epollfd = epoll_create1(0);
151 : if (eloop.epollfd < 0) {
152 : wpa_printf(MSG_ERROR, "%s: epoll_create1 failed. %s\n",
153 : __func__, strerror(errno));
154 : return -1;
155 : }
156 : eloop.readers.type = EVENT_TYPE_READ;
157 : eloop.writers.type = EVENT_TYPE_WRITE;
158 : eloop.exceptions.type = EVENT_TYPE_EXCEPTION;
159 : #endif /* CONFIG_ELOOP_EPOLL */
160 : #ifdef WPA_TRACE
161 105 : signal(SIGSEGV, eloop_sigsegv_handler);
162 : #endif /* WPA_TRACE */
163 105 : return 0;
164 : }
165 :
166 :
167 23753 : static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
168 : int sock, eloop_sock_handler handler,
169 : void *eloop_data, void *user_data)
170 : {
171 : #ifdef CONFIG_ELOOP_EPOLL
172 : struct eloop_sock *temp_table;
173 : struct epoll_event ev, *temp_events;
174 : int next;
175 : #endif /* CONFIG_ELOOP_EPOLL */
176 : struct eloop_sock *tmp;
177 : int new_max_sock;
178 :
179 23753 : if (sock > eloop.max_sock)
180 1207 : new_max_sock = sock;
181 : else
182 22546 : new_max_sock = eloop.max_sock;
183 :
184 23753 : if (table == NULL)
185 0 : return -1;
186 :
187 : #ifdef CONFIG_ELOOP_POLL
188 : if (new_max_sock >= eloop.max_pollfd_map) {
189 : struct pollfd **nmap;
190 : nmap = os_realloc_array(eloop.pollfds_map, new_max_sock + 50,
191 : sizeof(struct pollfd *));
192 : if (nmap == NULL)
193 : return -1;
194 :
195 : eloop.max_pollfd_map = new_max_sock + 50;
196 : eloop.pollfds_map = nmap;
197 : }
198 :
199 : if (eloop.count + 1 > eloop.max_poll_fds) {
200 : struct pollfd *n;
201 : int nmax = eloop.count + 1 + 50;
202 : n = os_realloc_array(eloop.pollfds, nmax,
203 : sizeof(struct pollfd));
204 : if (n == NULL)
205 : return -1;
206 :
207 : eloop.max_poll_fds = nmax;
208 : eloop.pollfds = n;
209 : }
210 : #endif /* CONFIG_ELOOP_POLL */
211 : #ifdef CONFIG_ELOOP_EPOLL
212 : if (new_max_sock >= eloop.epoll_max_fd) {
213 : next = eloop.epoll_max_fd == 0 ? 16 : eloop.epoll_max_fd * 2;
214 : temp_table = os_realloc_array(eloop.epoll_table, next,
215 : sizeof(struct eloop_sock));
216 : if (temp_table == NULL)
217 : return -1;
218 :
219 : eloop.epoll_max_fd = next;
220 : eloop.epoll_table = temp_table;
221 : }
222 :
223 : if (eloop.count + 1 > eloop.epoll_max_event_num) {
224 : next = eloop.epoll_max_event_num == 0 ? 8 :
225 : eloop.epoll_max_event_num * 2;
226 : temp_events = os_realloc_array(eloop.epoll_events, next,
227 : sizeof(struct epoll_event));
228 : if (temp_events == NULL) {
229 : wpa_printf(MSG_ERROR, "%s: malloc for epoll failed. "
230 : "%s\n", __func__, strerror(errno));
231 : return -1;
232 : }
233 :
234 : eloop.epoll_max_event_num = next;
235 : eloop.epoll_events = temp_events;
236 : }
237 : #endif /* CONFIG_ELOOP_EPOLL */
238 :
239 23753 : eloop_trace_sock_remove_ref(table);
240 23753 : tmp = os_realloc_array(table->table, table->count + 1,
241 : sizeof(struct eloop_sock));
242 23753 : if (tmp == NULL) {
243 9 : eloop_trace_sock_add_ref(table);
244 9 : return -1;
245 : }
246 :
247 23744 : tmp[table->count].sock = sock;
248 23744 : tmp[table->count].eloop_data = eloop_data;
249 23744 : tmp[table->count].user_data = user_data;
250 23744 : tmp[table->count].handler = handler;
251 23744 : wpa_trace_record(&tmp[table->count]);
252 23744 : table->count++;
253 23744 : table->table = tmp;
254 23744 : eloop.max_sock = new_max_sock;
255 23744 : eloop.count++;
256 23744 : table->changed = 1;
257 23744 : eloop_trace_sock_add_ref(table);
258 :
259 : #ifdef CONFIG_ELOOP_EPOLL
260 : os_memset(&ev, 0, sizeof(ev));
261 : switch (table->type) {
262 : case EVENT_TYPE_READ:
263 : ev.events = EPOLLIN;
264 : break;
265 : case EVENT_TYPE_WRITE:
266 : ev.events = EPOLLOUT;
267 : break;
268 : /*
269 : * Exceptions are always checked when using epoll, but I suppose it's
270 : * possible that someone registered a socket *only* for exception
271 : * handling.
272 : */
273 : case EVENT_TYPE_EXCEPTION:
274 : ev.events = EPOLLERR | EPOLLHUP;
275 : break;
276 : }
277 : ev.data.fd = sock;
278 : if (epoll_ctl(eloop.epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) {
279 : wpa_printf(MSG_ERROR, "%s: epoll_ctl(ADD) for fd=%d "
280 : "failed. %s\n", __func__, sock, strerror(errno));
281 : return -1;
282 : }
283 : os_memcpy(&eloop.epoll_table[sock], &table->table[table->count - 1],
284 : sizeof(struct eloop_sock));
285 : #endif /* CONFIG_ELOOP_EPOLL */
286 23744 : return 0;
287 : }
288 :
289 :
290 26196 : static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
291 : int sock)
292 : {
293 : int i;
294 :
295 26196 : if (table == NULL || table->table == NULL || table->count == 0)
296 1054 : return;
297 :
298 286997 : for (i = 0; i < table->count; i++) {
299 285599 : if (table->table[i].sock == sock)
300 23744 : break;
301 : }
302 25142 : if (i == table->count)
303 1398 : return;
304 23744 : eloop_trace_sock_remove_ref(table);
305 23744 : if (i != table->count - 1) {
306 10143 : os_memmove(&table->table[i], &table->table[i + 1],
307 : (table->count - i - 1) *
308 : sizeof(struct eloop_sock));
309 : }
310 23744 : table->count--;
311 23744 : eloop.count--;
312 23744 : table->changed = 1;
313 23744 : eloop_trace_sock_add_ref(table);
314 : #ifdef CONFIG_ELOOP_EPOLL
315 : if (epoll_ctl(eloop.epollfd, EPOLL_CTL_DEL, sock, NULL) < 0) {
316 : wpa_printf(MSG_ERROR, "%s: epoll_ctl(DEL) for fd=%d "
317 : "failed. %s\n", __func__, sock, strerror(errno));
318 : return;
319 : }
320 : os_memset(&eloop.epoll_table[sock], 0, sizeof(struct eloop_sock));
321 : #endif /* CONFIG_ELOOP_EPOLL */
322 : }
323 :
324 :
325 : #ifdef CONFIG_ELOOP_POLL
326 :
327 : static struct pollfd * find_pollfd(struct pollfd **pollfds_map, int fd, int mx)
328 : {
329 : if (fd < mx && fd >= 0)
330 : return pollfds_map[fd];
331 : return NULL;
332 : }
333 :
334 :
335 : static int eloop_sock_table_set_fds(struct eloop_sock_table *readers,
336 : struct eloop_sock_table *writers,
337 : struct eloop_sock_table *exceptions,
338 : struct pollfd *pollfds,
339 : struct pollfd **pollfds_map,
340 : int max_pollfd_map)
341 : {
342 : int i;
343 : int nxt = 0;
344 : int fd;
345 : struct pollfd *pfd;
346 :
347 : /* Clear pollfd lookup map. It will be re-populated below. */
348 : os_memset(pollfds_map, 0, sizeof(struct pollfd *) * max_pollfd_map);
349 :
350 : if (readers && readers->table) {
351 : for (i = 0; i < readers->count; i++) {
352 : fd = readers->table[i].sock;
353 : assert(fd >= 0 && fd < max_pollfd_map);
354 : pollfds[nxt].fd = fd;
355 : pollfds[nxt].events = POLLIN;
356 : pollfds[nxt].revents = 0;
357 : pollfds_map[fd] = &(pollfds[nxt]);
358 : nxt++;
359 : }
360 : }
361 :
362 : if (writers && writers->table) {
363 : for (i = 0; i < writers->count; i++) {
364 : /*
365 : * See if we already added this descriptor, update it
366 : * if so.
367 : */
368 : fd = writers->table[i].sock;
369 : assert(fd >= 0 && fd < max_pollfd_map);
370 : pfd = pollfds_map[fd];
371 : if (!pfd) {
372 : pfd = &(pollfds[nxt]);
373 : pfd->events = 0;
374 : pfd->fd = fd;
375 : pollfds[i].revents = 0;
376 : pollfds_map[fd] = pfd;
377 : nxt++;
378 : }
379 : pfd->events |= POLLOUT;
380 : }
381 : }
382 :
383 : /*
384 : * Exceptions are always checked when using poll, but I suppose it's
385 : * possible that someone registered a socket *only* for exception
386 : * handling. Set the POLLIN bit in this case.
387 : */
388 : if (exceptions && exceptions->table) {
389 : for (i = 0; i < exceptions->count; i++) {
390 : /*
391 : * See if we already added this descriptor, just use it
392 : * if so.
393 : */
394 : fd = exceptions->table[i].sock;
395 : assert(fd >= 0 && fd < max_pollfd_map);
396 : pfd = pollfds_map[fd];
397 : if (!pfd) {
398 : pfd = &(pollfds[nxt]);
399 : pfd->events = POLLIN;
400 : pfd->fd = fd;
401 : pollfds[i].revents = 0;
402 : pollfds_map[fd] = pfd;
403 : nxt++;
404 : }
405 : }
406 : }
407 :
408 : return nxt;
409 : }
410 :
411 :
412 : static int eloop_sock_table_dispatch_table(struct eloop_sock_table *table,
413 : struct pollfd **pollfds_map,
414 : int max_pollfd_map,
415 : short int revents)
416 : {
417 : int i;
418 : struct pollfd *pfd;
419 :
420 : if (!table || !table->table)
421 : return 0;
422 :
423 : table->changed = 0;
424 : for (i = 0; i < table->count; i++) {
425 : pfd = find_pollfd(pollfds_map, table->table[i].sock,
426 : max_pollfd_map);
427 : if (!pfd)
428 : continue;
429 :
430 : if (!(pfd->revents & revents))
431 : continue;
432 :
433 : table->table[i].handler(table->table[i].sock,
434 : table->table[i].eloop_data,
435 : table->table[i].user_data);
436 : if (table->changed)
437 : return 1;
438 : }
439 :
440 : return 0;
441 : }
442 :
443 :
444 : static void eloop_sock_table_dispatch(struct eloop_sock_table *readers,
445 : struct eloop_sock_table *writers,
446 : struct eloop_sock_table *exceptions,
447 : struct pollfd **pollfds_map,
448 : int max_pollfd_map)
449 : {
450 : if (eloop_sock_table_dispatch_table(readers, pollfds_map,
451 : max_pollfd_map, POLLIN | POLLERR |
452 : POLLHUP))
453 : return; /* pollfds may be invalid at this point */
454 :
455 : if (eloop_sock_table_dispatch_table(writers, pollfds_map,
456 : max_pollfd_map, POLLOUT))
457 : return; /* pollfds may be invalid at this point */
458 :
459 : eloop_sock_table_dispatch_table(exceptions, pollfds_map,
460 : max_pollfd_map, POLLERR | POLLHUP);
461 : }
462 :
463 : #endif /* CONFIG_ELOOP_POLL */
464 :
465 : #ifdef CONFIG_ELOOP_SELECT
466 :
467 2066595 : static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
468 : fd_set *fds)
469 : {
470 : int i;
471 :
472 2066595 : FD_ZERO(fds);
473 :
474 2066595 : if (table->table == NULL)
475 3005383 : return;
476 :
477 7798478 : for (i = 0; i < table->count; i++) {
478 6670671 : assert(table->table[i].sock >= 0);
479 6670671 : FD_SET(table->table[i].sock, fds);
480 : }
481 : }
482 :
483 :
484 1885566 : static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
485 : fd_set *fds)
486 : {
487 : int i;
488 :
489 1885566 : if (table == NULL || table->table == NULL)
490 2760894 : return;
491 :
492 1010238 : table->changed = 0;
493 6864374 : for (i = 0; i < table->count; i++) {
494 5868427 : if (FD_ISSET(table->table[i].sock, fds)) {
495 2251935 : table->table[i].handler(table->table[i].sock,
496 750645 : table->table[i].eloop_data,
497 750645 : table->table[i].user_data);
498 750645 : if (table->changed)
499 14291 : break;
500 : }
501 : }
502 : }
503 :
504 : #endif /* CONFIG_ELOOP_SELECT */
505 :
506 :
507 : #ifdef CONFIG_ELOOP_EPOLL
508 : static void eloop_sock_table_dispatch(struct epoll_event *events, int nfds)
509 : {
510 : struct eloop_sock *table;
511 : int i;
512 :
513 : for (i = 0; i < nfds; i++) {
514 : table = &eloop.epoll_table[events[i].data.fd];
515 : if (table->handler == NULL)
516 : continue;
517 : table->handler(table->sock, table->eloop_data,
518 : table->user_data);
519 : if (eloop.readers.changed ||
520 : eloop.writers.changed ||
521 : eloop.exceptions.changed)
522 : break;
523 : }
524 : }
525 : #endif /* CONFIG_ELOOP_EPOLL */
526 :
527 :
528 315 : static void eloop_sock_table_destroy(struct eloop_sock_table *table)
529 : {
530 315 : if (table) {
531 : int i;
532 315 : for (i = 0; i < table->count && table->table; i++) {
533 0 : wpa_printf(MSG_INFO, "ELOOP: remaining socket: "
534 : "sock=%d eloop_data=%p user_data=%p "
535 : "handler=%p",
536 0 : table->table[i].sock,
537 0 : table->table[i].eloop_data,
538 0 : table->table[i].user_data,
539 0 : table->table[i].handler);
540 0 : wpa_trace_dump_funcname("eloop unregistered socket "
541 : "handler",
542 0 : table->table[i].handler);
543 0 : wpa_trace_dump("eloop sock", &table->table[i]);
544 : }
545 315 : os_free(table->table);
546 : }
547 315 : }
548 :
549 :
550 21054 : int eloop_register_read_sock(int sock, eloop_sock_handler handler,
551 : void *eloop_data, void *user_data)
552 : {
553 21054 : return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
554 : eloop_data, user_data);
555 : }
556 :
557 :
558 21054 : void eloop_unregister_read_sock(int sock)
559 : {
560 21054 : eloop_unregister_sock(sock, EVENT_TYPE_READ);
561 21054 : }
562 :
563 :
564 49949 : static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
565 : {
566 49949 : switch (type) {
567 : case EVENT_TYPE_READ:
568 46791 : return &eloop.readers;
569 : case EVENT_TYPE_WRITE:
570 3140 : return &eloop.writers;
571 : case EVENT_TYPE_EXCEPTION:
572 18 : return &eloop.exceptions;
573 : }
574 :
575 0 : return NULL;
576 : }
577 :
578 :
579 23753 : int eloop_register_sock(int sock, eloop_event_type type,
580 : eloop_sock_handler handler,
581 : void *eloop_data, void *user_data)
582 : {
583 : struct eloop_sock_table *table;
584 :
585 23753 : assert(sock >= 0);
586 23753 : table = eloop_get_sock_table(type);
587 23753 : return eloop_sock_table_add_sock(table, sock, handler,
588 : eloop_data, user_data);
589 : }
590 :
591 :
592 26196 : void eloop_unregister_sock(int sock, eloop_event_type type)
593 : {
594 : struct eloop_sock_table *table;
595 :
596 26196 : table = eloop_get_sock_table(type);
597 26196 : eloop_sock_table_remove_sock(table, sock);
598 26196 : }
599 :
600 :
601 152266 : int eloop_register_timeout(unsigned int secs, unsigned int usecs,
602 : eloop_timeout_handler handler,
603 : void *eloop_data, void *user_data)
604 : {
605 : struct eloop_timeout *timeout, *tmp;
606 : os_time_t now_sec;
607 :
608 152266 : timeout = os_zalloc(sizeof(*timeout));
609 152266 : if (timeout == NULL)
610 36 : return -1;
611 152230 : if (os_get_reltime(&timeout->time) < 0) {
612 0 : os_free(timeout);
613 0 : return -1;
614 : }
615 152230 : now_sec = timeout->time.sec;
616 152230 : timeout->time.sec += secs;
617 152230 : if (timeout->time.sec < now_sec) {
618 : /*
619 : * Integer overflow - assume long enough timeout to be assumed
620 : * to be infinite, i.e., the timeout would never happen.
621 : */
622 0 : wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to "
623 : "ever happen - ignore it", secs);
624 0 : os_free(timeout);
625 0 : return 0;
626 : }
627 152230 : timeout->time.usec += usecs;
628 310669 : while (timeout->time.usec >= 1000000) {
629 6209 : timeout->time.sec++;
630 6209 : timeout->time.usec -= 1000000;
631 : }
632 152230 : timeout->eloop_data = eloop_data;
633 152230 : timeout->user_data = user_data;
634 152230 : timeout->handler = handler;
635 152230 : wpa_trace_add_ref(timeout, eloop, eloop_data);
636 152230 : wpa_trace_add_ref(timeout, user, user_data);
637 152230 : wpa_trace_record(timeout);
638 :
639 : /* Maintain timeouts in order of increasing time */
640 518131 : dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
641 500491 : if (os_reltime_before(&timeout->time, &tmp->time)) {
642 134590 : dl_list_add(tmp->list.prev, &timeout->list);
643 134590 : return 0;
644 : }
645 : }
646 17640 : dl_list_add_tail(&eloop.timeout, &timeout->list);
647 :
648 17640 : return 0;
649 : }
650 :
651 :
652 152230 : static void eloop_remove_timeout(struct eloop_timeout *timeout)
653 : {
654 152230 : dl_list_del(&timeout->list);
655 152230 : wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data);
656 152230 : wpa_trace_remove_ref(timeout, user, timeout->user_data);
657 152230 : os_free(timeout);
658 152230 : }
659 :
660 :
661 497794 : int eloop_cancel_timeout(eloop_timeout_handler handler,
662 : void *eloop_data, void *user_data)
663 : {
664 : struct eloop_timeout *timeout, *prev;
665 497794 : int removed = 0;
666 :
667 4120295 : dl_list_for_each_safe(timeout, prev, &eloop.timeout,
668 : struct eloop_timeout, list) {
669 3862062 : if (timeout->handler == handler &&
670 375063 : (timeout->eloop_data == eloop_data ||
671 110081 : eloop_data == ELOOP_ALL_CTX) &&
672 148525 : (timeout->user_data == user_data ||
673 : user_data == ELOOP_ALL_CTX)) {
674 71639 : eloop_remove_timeout(timeout);
675 71639 : removed++;
676 : }
677 : }
678 :
679 497794 : return removed;
680 : }
681 :
682 :
683 23 : int eloop_cancel_timeout_one(eloop_timeout_handler handler,
684 : void *eloop_data, void *user_data,
685 : struct os_reltime *remaining)
686 : {
687 : struct eloop_timeout *timeout, *prev;
688 23 : int removed = 0;
689 : struct os_reltime now;
690 :
691 23 : os_get_reltime(&now);
692 23 : remaining->sec = remaining->usec = 0;
693 :
694 56 : dl_list_for_each_safe(timeout, prev, &eloop.timeout,
695 : struct eloop_timeout, list) {
696 45 : if (timeout->handler == handler &&
697 12 : (timeout->eloop_data == eloop_data) &&
698 6 : (timeout->user_data == user_data)) {
699 6 : removed = 1;
700 6 : if (os_reltime_before(&now, &timeout->time))
701 6 : os_reltime_sub(&timeout->time, &now, remaining);
702 6 : eloop_remove_timeout(timeout);
703 6 : break;
704 : }
705 : }
706 23 : return removed;
707 : }
708 :
709 :
710 41819 : int eloop_is_timeout_registered(eloop_timeout_handler handler,
711 : void *eloop_data, void *user_data)
712 : {
713 : struct eloop_timeout *tmp;
714 :
715 158427 : dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
716 153168 : if (tmp->handler == handler &&
717 40185 : tmp->eloop_data == eloop_data &&
718 20092 : tmp->user_data == user_data)
719 16467 : return 1;
720 : }
721 :
722 25352 : return 0;
723 : }
724 :
725 :
726 7327 : int eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs,
727 : eloop_timeout_handler handler, void *eloop_data,
728 : void *user_data)
729 : {
730 : struct os_reltime now, requested, remaining;
731 : struct eloop_timeout *tmp;
732 :
733 37483 : dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
734 31352 : if (tmp->handler == handler &&
735 1196 : tmp->eloop_data == eloop_data &&
736 598 : tmp->user_data == user_data) {
737 598 : requested.sec = req_secs;
738 598 : requested.usec = req_usecs;
739 598 : os_get_reltime(&now);
740 598 : os_reltime_sub(&tmp->time, &now, &remaining);
741 598 : if (os_reltime_before(&requested, &remaining)) {
742 173 : eloop_cancel_timeout(handler, eloop_data,
743 : user_data);
744 173 : eloop_register_timeout(requested.sec,
745 173 : requested.usec,
746 : handler, eloop_data,
747 : user_data);
748 173 : return 1;
749 : }
750 425 : return 0;
751 : }
752 : }
753 :
754 6729 : return -1;
755 : }
756 :
757 :
758 9 : int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs,
759 : eloop_timeout_handler handler, void *eloop_data,
760 : void *user_data)
761 : {
762 : struct os_reltime now, requested, remaining;
763 : struct eloop_timeout *tmp;
764 :
765 16 : dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
766 23 : if (tmp->handler == handler &&
767 16 : tmp->eloop_data == eloop_data &&
768 8 : tmp->user_data == user_data) {
769 8 : requested.sec = req_secs;
770 8 : requested.usec = req_usecs;
771 8 : os_get_reltime(&now);
772 8 : os_reltime_sub(&tmp->time, &now, &remaining);
773 8 : if (os_reltime_before(&remaining, &requested)) {
774 8 : eloop_cancel_timeout(handler, eloop_data,
775 : user_data);
776 8 : eloop_register_timeout(requested.sec,
777 8 : requested.usec,
778 : handler, eloop_data,
779 : user_data);
780 8 : return 1;
781 : }
782 0 : return 0;
783 : }
784 : }
785 :
786 1 : return -1;
787 : }
788 :
789 :
790 : #ifndef CONFIG_NATIVE_WINDOWS
791 0 : static void eloop_handle_alarm(int sig)
792 : {
793 0 : wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in "
794 : "two seconds. Looks like there\n"
795 : "is a bug that ends up in a busy loop that "
796 : "prevents clean shutdown.\n"
797 : "Killing program forcefully.\n");
798 0 : exit(1);
799 : }
800 : #endif /* CONFIG_NATIVE_WINDOWS */
801 :
802 :
803 1442 : static void eloop_handle_signal(int sig)
804 : {
805 : int i;
806 :
807 : #ifndef CONFIG_NATIVE_WINDOWS
808 1442 : if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) {
809 : /* Use SIGALRM to break out from potential busy loops that
810 : * would not allow the program to be killed. */
811 43 : eloop.pending_terminate = 1;
812 43 : signal(SIGALRM, eloop_handle_alarm);
813 43 : alarm(2);
814 : }
815 : #endif /* CONFIG_NATIVE_WINDOWS */
816 :
817 1442 : eloop.signaled++;
818 1523 : for (i = 0; i < eloop.signal_count; i++) {
819 1523 : if (eloop.signals[i].sig == sig) {
820 1442 : eloop.signals[i].signaled++;
821 1442 : break;
822 : }
823 : }
824 1442 : }
825 :
826 :
827 688868 : static void eloop_process_pending_signals(void)
828 : {
829 : int i;
830 :
831 688868 : if (eloop.signaled == 0)
832 1376305 : return;
833 1431 : eloop.signaled = 0;
834 :
835 1431 : if (eloop.pending_terminate) {
836 : #ifndef CONFIG_NATIVE_WINDOWS
837 43 : alarm(0);
838 : #endif /* CONFIG_NATIVE_WINDOWS */
839 43 : eloop.pending_terminate = 0;
840 : }
841 :
842 7133 : for (i = 0; i < eloop.signal_count; i++) {
843 5702 : if (eloop.signals[i].signaled) {
844 1432 : eloop.signals[i].signaled = 0;
845 2864 : eloop.signals[i].handler(eloop.signals[i].sig,
846 1432 : eloop.signals[i].user_data);
847 : }
848 : }
849 : }
850 :
851 :
852 237 : int eloop_register_signal(int sig, eloop_signal_handler handler,
853 : void *user_data)
854 : {
855 : struct eloop_signal *tmp;
856 :
857 237 : tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1,
858 : sizeof(struct eloop_signal));
859 237 : if (tmp == NULL)
860 0 : return -1;
861 :
862 237 : tmp[eloop.signal_count].sig = sig;
863 237 : tmp[eloop.signal_count].user_data = user_data;
864 237 : tmp[eloop.signal_count].handler = handler;
865 237 : tmp[eloop.signal_count].signaled = 0;
866 237 : eloop.signal_count++;
867 237 : eloop.signals = tmp;
868 237 : signal(sig, eloop_handle_signal);
869 :
870 237 : return 0;
871 : }
872 :
873 :
874 77 : int eloop_register_signal_terminate(eloop_signal_handler handler,
875 : void *user_data)
876 : {
877 77 : int ret = eloop_register_signal(SIGINT, handler, user_data);
878 77 : if (ret == 0)
879 77 : ret = eloop_register_signal(SIGTERM, handler, user_data);
880 77 : return ret;
881 : }
882 :
883 :
884 27 : int eloop_register_signal_reconfig(eloop_signal_handler handler,
885 : void *user_data)
886 : {
887 : #ifdef CONFIG_NATIVE_WINDOWS
888 : return 0;
889 : #else /* CONFIG_NATIVE_WINDOWS */
890 27 : return eloop_register_signal(SIGHUP, handler, user_data);
891 : #endif /* CONFIG_NATIVE_WINDOWS */
892 : }
893 :
894 :
895 44 : void eloop_run(void)
896 : {
897 : #ifdef CONFIG_ELOOP_POLL
898 : int num_poll_fds;
899 : int timeout_ms = 0;
900 : #endif /* CONFIG_ELOOP_POLL */
901 : #ifdef CONFIG_ELOOP_SELECT
902 : fd_set *rfds, *wfds, *efds;
903 : struct timeval _tv;
904 : #endif /* CONFIG_ELOOP_SELECT */
905 : #ifdef CONFIG_ELOOP_EPOLL
906 : int timeout_ms = -1;
907 : #endif /* CONFIG_ELOOP_EPOLL */
908 : int res;
909 : struct os_reltime tv, now;
910 :
911 : #ifdef CONFIG_ELOOP_SELECT
912 44 : rfds = os_malloc(sizeof(*rfds));
913 44 : wfds = os_malloc(sizeof(*wfds));
914 44 : efds = os_malloc(sizeof(*efds));
915 44 : if (rfds == NULL || wfds == NULL || efds == NULL)
916 : goto out;
917 : #endif /* CONFIG_ELOOP_SELECT */
918 :
919 1377821 : while (!eloop.terminate &&
920 688868 : (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||
921 0 : eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
922 : struct eloop_timeout *timeout;
923 :
924 688868 : if (eloop.pending_terminate) {
925 : /*
926 : * This may happen in some corner cases where a signal
927 : * is received during a blocking operation. We need to
928 : * process the pending signals and exit if requested to
929 : * avoid hitting the SIGALRM limit if the blocking
930 : * operation took more than two seconds.
931 : */
932 3 : eloop_process_pending_signals();
933 3 : if (eloop.terminate)
934 3 : break;
935 : }
936 :
937 688865 : timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
938 : list);
939 688865 : if (timeout) {
940 688865 : os_get_reltime(&now);
941 688865 : if (os_reltime_before(&now, &timeout->time))
942 624949 : os_reltime_sub(&timeout->time, &now, &tv);
943 : else
944 63916 : tv.sec = tv.usec = 0;
945 : #if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL)
946 : timeout_ms = tv.sec * 1000 + tv.usec / 1000;
947 : #endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */
948 : #ifdef CONFIG_ELOOP_SELECT
949 688865 : _tv.tv_sec = tv.sec;
950 688865 : _tv.tv_usec = tv.usec;
951 : #endif /* CONFIG_ELOOP_SELECT */
952 : }
953 :
954 : #ifdef CONFIG_ELOOP_POLL
955 : num_poll_fds = eloop_sock_table_set_fds(
956 : &eloop.readers, &eloop.writers, &eloop.exceptions,
957 : eloop.pollfds, eloop.pollfds_map,
958 : eloop.max_pollfd_map);
959 : res = poll(eloop.pollfds, num_poll_fds,
960 : timeout ? timeout_ms : -1);
961 : #endif /* CONFIG_ELOOP_POLL */
962 : #ifdef CONFIG_ELOOP_SELECT
963 688865 : eloop_sock_table_set_fds(&eloop.readers, rfds);
964 688865 : eloop_sock_table_set_fds(&eloop.writers, wfds);
965 688865 : eloop_sock_table_set_fds(&eloop.exceptions, efds);
966 688865 : res = select(eloop.max_sock + 1, rfds, wfds, efds,
967 : timeout ? &_tv : NULL);
968 : #endif /* CONFIG_ELOOP_SELECT */
969 : #ifdef CONFIG_ELOOP_EPOLL
970 : if (eloop.count == 0) {
971 : res = 0;
972 : } else {
973 : res = epoll_wait(eloop.epollfd, eloop.epoll_events,
974 : eloop.count, timeout_ms);
975 : }
976 : #endif /* CONFIG_ELOOP_EPOLL */
977 688865 : if (res < 0 && errno != EINTR && errno != 0) {
978 0 : wpa_printf(MSG_ERROR, "eloop: %s: %s",
979 : #ifdef CONFIG_ELOOP_POLL
980 : "poll"
981 : #endif /* CONFIG_ELOOP_POLL */
982 : #ifdef CONFIG_ELOOP_SELECT
983 : "select"
984 : #endif /* CONFIG_ELOOP_SELECT */
985 : #ifdef CONFIG_ELOOP_EPOLL
986 : "epoll"
987 : #endif /* CONFIG_ELOOP_EPOLL */
988 0 : , strerror(errno));
989 0 : goto out;
990 : }
991 :
992 688865 : eloop.readers.changed = 0;
993 688865 : eloop.writers.changed = 0;
994 688865 : eloop.exceptions.changed = 0;
995 :
996 688865 : eloop_process_pending_signals();
997 :
998 : /* check if some registered timeouts have occurred */
999 688865 : timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
1000 : list);
1001 688865 : if (timeout) {
1002 688865 : os_get_reltime(&now);
1003 688865 : if (!os_reltime_before(&now, &timeout->time)) {
1004 80585 : void *eloop_data = timeout->eloop_data;
1005 80585 : void *user_data = timeout->user_data;
1006 80585 : eloop_timeout_handler handler =
1007 : timeout->handler;
1008 80585 : eloop_remove_timeout(timeout);
1009 80585 : handler(eloop_data, user_data);
1010 : }
1011 :
1012 : }
1013 :
1014 688865 : if (res <= 0)
1015 59626 : continue;
1016 :
1017 1258076 : if (eloop.readers.changed ||
1018 1257359 : eloop.writers.changed ||
1019 628522 : eloop.exceptions.changed) {
1020 : /*
1021 : * Sockets may have been closed and reopened with the
1022 : * same FD in the signal or timeout handlers, so we
1023 : * must skip the previous results and check again
1024 : * whether any of the currently registered sockets have
1025 : * events.
1026 : */
1027 717 : continue;
1028 : }
1029 :
1030 : #ifdef CONFIG_ELOOP_POLL
1031 : eloop_sock_table_dispatch(&eloop.readers, &eloop.writers,
1032 : &eloop.exceptions, eloop.pollfds_map,
1033 : eloop.max_pollfd_map);
1034 : #endif /* CONFIG_ELOOP_POLL */
1035 : #ifdef CONFIG_ELOOP_SELECT
1036 628522 : eloop_sock_table_dispatch(&eloop.readers, rfds);
1037 628522 : eloop_sock_table_dispatch(&eloop.writers, wfds);
1038 628522 : eloop_sock_table_dispatch(&eloop.exceptions, efds);
1039 : #endif /* CONFIG_ELOOP_SELECT */
1040 : #ifdef CONFIG_ELOOP_EPOLL
1041 : eloop_sock_table_dispatch(eloop.epoll_events, res);
1042 : #endif /* CONFIG_ELOOP_EPOLL */
1043 : }
1044 :
1045 44 : eloop.terminate = 0;
1046 : out:
1047 : #ifdef CONFIG_ELOOP_SELECT
1048 44 : os_free(rfds);
1049 44 : os_free(wfds);
1050 44 : os_free(efds);
1051 : #endif /* CONFIG_ELOOP_SELECT */
1052 44 : return;
1053 : }
1054 :
1055 :
1056 44 : void eloop_terminate(void)
1057 : {
1058 44 : eloop.terminate = 1;
1059 44 : }
1060 :
1061 :
1062 105 : void eloop_destroy(void)
1063 : {
1064 : struct eloop_timeout *timeout, *prev;
1065 : struct os_reltime now;
1066 :
1067 105 : os_get_reltime(&now);
1068 105 : dl_list_for_each_safe(timeout, prev, &eloop.timeout,
1069 : struct eloop_timeout, list) {
1070 : int sec, usec;
1071 0 : sec = timeout->time.sec - now.sec;
1072 0 : usec = timeout->time.usec - now.usec;
1073 0 : if (timeout->time.usec < now.usec) {
1074 0 : sec--;
1075 0 : usec += 1000000;
1076 : }
1077 0 : wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d "
1078 : "eloop_data=%p user_data=%p handler=%p",
1079 : sec, usec, timeout->eloop_data, timeout->user_data,
1080 : timeout->handler);
1081 0 : wpa_trace_dump_funcname("eloop unregistered timeout handler",
1082 0 : timeout->handler);
1083 0 : wpa_trace_dump("eloop timeout", timeout);
1084 0 : eloop_remove_timeout(timeout);
1085 : }
1086 105 : eloop_sock_table_destroy(&eloop.readers);
1087 105 : eloop_sock_table_destroy(&eloop.writers);
1088 105 : eloop_sock_table_destroy(&eloop.exceptions);
1089 105 : os_free(eloop.signals);
1090 :
1091 : #ifdef CONFIG_ELOOP_POLL
1092 : os_free(eloop.pollfds);
1093 : os_free(eloop.pollfds_map);
1094 : #endif /* CONFIG_ELOOP_POLL */
1095 : #ifdef CONFIG_ELOOP_EPOLL
1096 : os_free(eloop.epoll_table);
1097 : os_free(eloop.epoll_events);
1098 : close(eloop.epollfd);
1099 : #endif /* CONFIG_ELOOP_EPOLL */
1100 105 : }
1101 :
1102 :
1103 4940 : int eloop_terminated(void)
1104 : {
1105 4940 : return eloop.terminate || eloop.pending_terminate;
1106 : }
1107 :
1108 :
1109 1 : void eloop_wait_for_read_sock(int sock)
1110 : {
1111 : #ifdef CONFIG_ELOOP_POLL
1112 : struct pollfd pfd;
1113 :
1114 : if (sock < 0)
1115 : return;
1116 :
1117 : os_memset(&pfd, 0, sizeof(pfd));
1118 : pfd.fd = sock;
1119 : pfd.events = POLLIN;
1120 :
1121 : poll(&pfd, 1, -1);
1122 : #endif /* CONFIG_ELOOP_POLL */
1123 : #if defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL)
1124 : /*
1125 : * We can use epoll() here. But epoll() requres 4 system calls.
1126 : * epoll_create1(), epoll_ctl() for ADD, epoll_wait, and close() for
1127 : * epoll fd. So select() is better for performance here.
1128 : */
1129 : fd_set rfds;
1130 :
1131 1 : if (sock < 0)
1132 1 : return;
1133 :
1134 1 : FD_ZERO(&rfds);
1135 1 : FD_SET(sock, &rfds);
1136 1 : select(sock + 1, &rfds, NULL, NULL, NULL);
1137 : #endif /* defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) */
1138 : }
1139 :
1140 : #ifdef CONFIG_ELOOP_SELECT
1141 : #undef CONFIG_ELOOP_SELECT
1142 : #endif /* CONFIG_ELOOP_SELECT */
|