2 * Event loop based on select() loop
3 * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
25 eloop_sock_handler handler
;
28 struct eloop_timeout
{
32 eloop_timeout_handler handler
;
33 struct eloop_timeout
*next
;
39 eloop_signal_handler handler
;
43 struct eloop_sock_table
{
45 struct eloop_sock
*table
;
54 struct eloop_sock_table readers
;
55 struct eloop_sock_table writers
;
56 struct eloop_sock_table exceptions
;
58 struct eloop_timeout
*timeout
;
61 struct eloop_signal
*signals
;
63 int pending_terminate
;
66 int reader_table_changed
;
69 static struct eloop_data eloop
;
72 int eloop_init(void *user_data
)
74 os_memset(&eloop
, 0, sizeof(eloop
));
75 eloop
.user_data
= user_data
;
80 static int eloop_sock_table_add_sock(struct eloop_sock_table
*table
,
81 int sock
, eloop_sock_handler handler
,
82 void *eloop_data
, void *user_data
)
84 struct eloop_sock
*tmp
;
89 tmp
= (struct eloop_sock
*)
90 os_realloc(table
->table
,
91 (table
->count
+ 1) * sizeof(struct eloop_sock
));
95 tmp
[table
->count
].sock
= sock
;
96 tmp
[table
->count
].eloop_data
= eloop_data
;
97 tmp
[table
->count
].user_data
= user_data
;
98 tmp
[table
->count
].handler
= handler
;
101 if (sock
> eloop
.max_sock
)
102 eloop
.max_sock
= sock
;
109 static void eloop_sock_table_remove_sock(struct eloop_sock_table
*table
,
114 if (table
== NULL
|| table
->table
== NULL
|| table
->count
== 0)
117 for (i
= 0; i
< table
->count
; i
++) {
118 if (table
->table
[i
].sock
== sock
)
121 if (i
== table
->count
)
123 if (i
!= table
->count
- 1) {
124 os_memmove(&table
->table
[i
], &table
->table
[i
+ 1],
125 (table
->count
- i
- 1) *
126 sizeof(struct eloop_sock
));
133 static void eloop_sock_table_set_fds(struct eloop_sock_table
*table
,
140 if (table
->table
== NULL
)
143 for (i
= 0; i
< table
->count
; i
++)
144 FD_SET(table
->table
[i
].sock
, fds
);
148 static void eloop_sock_table_dispatch(struct eloop_sock_table
*table
,
153 if (table
== NULL
|| table
->table
== NULL
)
157 for (i
= 0; i
< table
->count
; i
++) {
158 if (FD_ISSET(table
->table
[i
].sock
, fds
)) {
159 table
->table
[i
].handler(table
->table
[i
].sock
,
160 table
->table
[i
].eloop_data
,
161 table
->table
[i
].user_data
);
169 static void eloop_sock_table_destroy(struct eloop_sock_table
*table
)
173 for (i
= 0; i
< table
->count
&& table
->table
; i
++) {
174 printf("ELOOP: remaining socket: sock=%d "
175 "eloop_data=%p user_data=%p handler=%p\n",
176 table
->table
[i
].sock
,
177 table
->table
[i
].eloop_data
,
178 table
->table
[i
].user_data
,
179 table
->table
[i
].handler
);
181 os_free(table
->table
);
186 int eloop_register_read_sock(int sock
, eloop_sock_handler handler
,
187 void *eloop_data
, void *user_data
)
189 return eloop_register_sock(sock
, EVENT_TYPE_READ
, handler
,
190 eloop_data
, user_data
);
194 void eloop_unregister_read_sock(int sock
)
196 eloop_unregister_sock(sock
, EVENT_TYPE_READ
);
200 static struct eloop_sock_table
*eloop_get_sock_table(eloop_event_type type
)
203 case EVENT_TYPE_READ
:
204 return &eloop
.readers
;
205 case EVENT_TYPE_WRITE
:
206 return &eloop
.writers
;
207 case EVENT_TYPE_EXCEPTION
:
208 return &eloop
.exceptions
;
215 int eloop_register_sock(int sock
, eloop_event_type type
,
216 eloop_sock_handler handler
,
217 void *eloop_data
, void *user_data
)
219 struct eloop_sock_table
*table
;
221 table
= eloop_get_sock_table(type
);
222 return eloop_sock_table_add_sock(table
, sock
, handler
,
223 eloop_data
, user_data
);
227 void eloop_unregister_sock(int sock
, eloop_event_type type
)
229 struct eloop_sock_table
*table
;
231 table
= eloop_get_sock_table(type
);
232 eloop_sock_table_remove_sock(table
, sock
);
236 int eloop_register_timeout(unsigned int secs
, unsigned int usecs
,
237 eloop_timeout_handler handler
,
238 void *eloop_data
, void *user_data
)
240 struct eloop_timeout
*timeout
, *tmp
, *prev
;
242 timeout
= os_malloc(sizeof(*timeout
));
245 if (os_get_time(&timeout
->time
) < 0) {
249 timeout
->time
.sec
+= secs
;
250 timeout
->time
.usec
+= usecs
;
251 while (timeout
->time
.usec
>= 1000000) {
253 timeout
->time
.usec
-= 1000000;
255 timeout
->eloop_data
= eloop_data
;
256 timeout
->user_data
= user_data
;
257 timeout
->handler
= handler
;
258 timeout
->next
= NULL
;
260 if (eloop
.timeout
== NULL
) {
261 eloop
.timeout
= timeout
;
267 while (tmp
!= NULL
) {
268 if (os_time_before(&timeout
->time
, &tmp
->time
))
275 timeout
->next
= eloop
.timeout
;
276 eloop
.timeout
= timeout
;
278 timeout
->next
= prev
->next
;
279 prev
->next
= timeout
;
286 int eloop_cancel_timeout(eloop_timeout_handler handler
,
287 void *eloop_data
, void *user_data
)
289 struct eloop_timeout
*timeout
, *prev
, *next
;
293 timeout
= eloop
.timeout
;
294 while (timeout
!= NULL
) {
295 next
= timeout
->next
;
297 if (timeout
->handler
== handler
&&
298 (timeout
->eloop_data
== eloop_data
||
299 eloop_data
== ELOOP_ALL_CTX
) &&
300 (timeout
->user_data
== user_data
||
301 user_data
== ELOOP_ALL_CTX
)) {
303 eloop
.timeout
= next
;
318 int eloop_is_timeout_registered(eloop_timeout_handler handler
,
319 void *eloop_data
, void *user_data
)
321 struct eloop_timeout
*tmp
;
324 while (tmp
!= NULL
) {
325 if (tmp
->handler
== handler
&&
326 tmp
->eloop_data
== eloop_data
&&
327 tmp
->user_data
== user_data
)
337 #ifndef CONFIG_NATIVE_WINDOWS
338 static void eloop_handle_alarm(int sig
)
340 fprintf(stderr
, "eloop: could not process SIGINT or SIGTERM in two "
341 "seconds. Looks like there\n"
342 "is a bug that ends up in a busy loop that "
343 "prevents clean shutdown.\n"
344 "Killing program forcefully.\n");
347 #endif /* CONFIG_NATIVE_WINDOWS */
350 static void eloop_handle_signal(int sig
)
354 #ifndef CONFIG_NATIVE_WINDOWS
355 if ((sig
== SIGINT
|| sig
== SIGTERM
) && !eloop
.pending_terminate
) {
356 /* Use SIGALRM to break out from potential busy loops that
357 * would not allow the program to be killed. */
358 eloop
.pending_terminate
= 1;
359 signal(SIGALRM
, eloop_handle_alarm
);
362 #endif /* CONFIG_NATIVE_WINDOWS */
365 for (i
= 0; i
< eloop
.signal_count
; i
++) {
366 if (eloop
.signals
[i
].sig
== sig
) {
367 eloop
.signals
[i
].signaled
++;
374 static void eloop_process_pending_signals(void)
378 if (eloop
.signaled
== 0)
382 if (eloop
.pending_terminate
) {
383 #ifndef CONFIG_NATIVE_WINDOWS
385 #endif /* CONFIG_NATIVE_WINDOWS */
386 eloop
.pending_terminate
= 0;
389 for (i
= 0; i
< eloop
.signal_count
; i
++) {
390 if (eloop
.signals
[i
].signaled
) {
391 eloop
.signals
[i
].signaled
= 0;
392 eloop
.signals
[i
].handler(eloop
.signals
[i
].sig
,
394 eloop
.signals
[i
].user_data
);
400 int eloop_register_signal(int sig
, eloop_signal_handler handler
,
403 struct eloop_signal
*tmp
;
405 tmp
= (struct eloop_signal
*)
406 os_realloc(eloop
.signals
,
407 (eloop
.signal_count
+ 1) *
408 sizeof(struct eloop_signal
));
412 tmp
[eloop
.signal_count
].sig
= sig
;
413 tmp
[eloop
.signal_count
].user_data
= user_data
;
414 tmp
[eloop
.signal_count
].handler
= handler
;
415 tmp
[eloop
.signal_count
].signaled
= 0;
416 eloop
.signal_count
++;
418 signal(sig
, eloop_handle_signal
);
424 int eloop_register_signal_terminate(eloop_signal_handler handler
,
427 int ret
= eloop_register_signal(SIGINT
, handler
, user_data
);
429 ret
= eloop_register_signal(SIGTERM
, handler
, user_data
);
434 int eloop_register_signal_reconfig(eloop_signal_handler handler
,
437 #ifdef CONFIG_NATIVE_WINDOWS
439 #else /* CONFIG_NATIVE_WINDOWS */
440 return eloop_register_signal(SIGHUP
, handler
, user_data
);
441 #endif /* CONFIG_NATIVE_WINDOWS */
447 fd_set
*rfds
, *wfds
, *efds
;
450 struct os_time tv
, now
;
452 rfds
= os_malloc(sizeof(*rfds
));
453 wfds
= os_malloc(sizeof(*wfds
));
454 efds
= os_malloc(sizeof(*efds
));
455 if (rfds
== NULL
|| wfds
== NULL
|| efds
== NULL
) {
456 printf("eloop_run - malloc failed\n");
460 while (!eloop
.terminate
&&
461 (eloop
.timeout
|| eloop
.readers
.count
> 0 ||
462 eloop
.writers
.count
> 0 || eloop
.exceptions
.count
> 0)) {
465 if (os_time_before(&now
, &eloop
.timeout
->time
))
466 os_time_sub(&eloop
.timeout
->time
, &now
, &tv
);
468 tv
.sec
= tv
.usec
= 0;
470 printf("next timeout in %lu.%06lu sec\n",
474 _tv
.tv_usec
= tv
.usec
;
477 eloop_sock_table_set_fds(&eloop
.readers
, rfds
);
478 eloop_sock_table_set_fds(&eloop
.writers
, wfds
);
479 eloop_sock_table_set_fds(&eloop
.exceptions
, efds
);
480 res
= select(eloop
.max_sock
+ 1, rfds
, wfds
, efds
,
481 eloop
.timeout
? &_tv
: NULL
);
482 if (res
< 0 && errno
!= EINTR
&& errno
!= 0) {
486 eloop_process_pending_signals();
488 /* check if some registered timeouts have occurred */
490 struct eloop_timeout
*tmp
;
493 if (!os_time_before(&now
, &eloop
.timeout
->time
)) {
495 eloop
.timeout
= eloop
.timeout
->next
;
496 tmp
->handler(tmp
->eloop_data
,
506 eloop_sock_table_dispatch(&eloop
.readers
, rfds
);
507 eloop_sock_table_dispatch(&eloop
.writers
, wfds
);
508 eloop_sock_table_dispatch(&eloop
.exceptions
, efds
);
518 void eloop_terminate(void)
524 void eloop_destroy(void)
526 struct eloop_timeout
*timeout
, *prev
;
529 timeout
= eloop
.timeout
;
532 while (timeout
!= NULL
) {
535 timeout
= timeout
->next
;
536 sec
= prev
->time
.sec
- now
.sec
;
537 usec
= prev
->time
.usec
- now
.usec
;
538 if (prev
->time
.usec
< now
.usec
) {
542 printf("ELOOP: remaining timeout: %d.%06d eloop_data=%p "
543 "user_data=%p handler=%p\n",
544 sec
, usec
, prev
->eloop_data
, prev
->user_data
,
548 eloop_sock_table_destroy(&eloop
.readers
);
549 eloop_sock_table_destroy(&eloop
.writers
);
550 eloop_sock_table_destroy(&eloop
.exceptions
);
551 os_free(eloop
.signals
);
555 int eloop_terminated(void)
557 return eloop
.terminate
;
561 void eloop_wait_for_read_sock(int sock
)
570 select(sock
+ 1, &rfds
, NULL
, NULL
, NULL
);
574 void * eloop_get_user_data(void)
576 return eloop
.user_data
;