Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : main select loop and event handling
4 : Copyright (C) Andrew Tridgell 2003
5 : Copyright (C) Stefan Metzmacher 2009
6 :
7 : ** NOTE! The following LGPL license applies to the tevent
8 : ** library. This does NOT imply that all of Samba is released
9 : ** under the LGPL
10 :
11 : This library is free software; you can redistribute it and/or
12 : modify it under the terms of the GNU Lesser General Public
13 : License as published by the Free Software Foundation; either
14 : version 3 of the License, or (at your option) any later version.
15 :
16 : This library is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 : Lesser General Public License for more details.
20 :
21 : You should have received a copy of the GNU Lesser General Public
22 : License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : /*
26 : PLEASE READ THIS BEFORE MODIFYING!
27 :
28 : This module is a general abstraction for the main select loop and
29 : event handling. Do not ever put any localised hacks in here, instead
30 : register one of the possible event types and implement that event
31 : somewhere else.
32 :
33 : There are 2 types of event handling that are handled in this module:
34 :
35 : 1) a file descriptor becoming readable or writeable. This is mostly
36 : used for network sockets, but can be used for any type of file
37 : descriptor. You may only register one handler for each file
38 : descriptor/io combination or you will get unpredictable results
39 : (this means that you can have a handler for read events, and a
40 : separate handler for write events, but not two handlers that are
41 : both handling read events)
42 :
43 : 2) a timed event. You can register an event that happens at a
44 : specific time. You can register as many of these as you
45 : like. They are single shot - add a new timed event in the event
46 : handler to get another event.
47 :
48 : To setup a set of events you first need to create a event_context
49 : structure using the function tevent_context_init(); This returns a
50 : 'struct tevent_context' that you use in all subsequent calls.
51 :
52 : After that you can add/remove events that you are interested in
53 : using tevent_add_*() and talloc_free()
54 :
55 : Finally, you call tevent_loop_wait_once() to block waiting for one of the
56 : events to occor or tevent_loop_wait() which will loop
57 : forever.
58 :
59 : */
60 : #include "replace.h"
61 : #include "system/filesys.h"
62 : #ifdef HAVE_PTHREAD
63 : #include "system/threads.h"
64 : #endif
65 : #define TEVENT_DEPRECATED 1
66 : #include "tevent.h"
67 : #include "tevent_internal.h"
68 : #include "tevent_util.h"
69 : #ifdef HAVE_EVENTFD
70 : #include <sys/eventfd.h>
71 : #endif
72 :
73 : struct tevent_ops_list {
74 : struct tevent_ops_list *next, *prev;
75 : const char *name;
76 : const struct tevent_ops *ops;
77 : };
78 :
79 : /* list of registered event backends */
80 : static struct tevent_ops_list *tevent_backends = NULL;
81 : static char *tevent_default_backend = NULL;
82 :
83 : /*
84 : register an events backend
85 : */
86 303516 : bool tevent_register_backend(const char *name, const struct tevent_ops *ops)
87 : {
88 5904 : struct tevent_ops_list *e;
89 :
90 758790 : for (e = tevent_backends; e != NULL; e = e->next) {
91 455274 : if (0 == strcmp(e->name, name)) {
92 : /* already registered, skip it */
93 0 : return true;
94 : }
95 : }
96 :
97 303516 : e = talloc(NULL, struct tevent_ops_list);
98 303516 : if (e == NULL) return false;
99 :
100 303516 : e->name = name;
101 303516 : e->ops = ops;
102 303516 : DLIST_ADD(tevent_backends, e);
103 :
104 297612 : return true;
105 : }
106 :
107 : /*
108 : set the default event backend
109 : */
110 0 : void tevent_set_default_backend(const char *backend)
111 : {
112 0 : talloc_free(tevent_default_backend);
113 0 : tevent_default_backend = talloc_strdup(NULL, backend);
114 0 : }
115 :
116 : /*
117 : initialise backends if not already done
118 : */
119 249216296 : static void tevent_backend_init(void)
120 : {
121 9162825 : static bool done;
122 :
123 249216296 : if (done) {
124 239979068 : return;
125 : }
126 :
127 75879 : done = true;
128 :
129 75879 : tevent_poll_init();
130 75879 : tevent_poll_mt_init();
131 : #if defined(HAVE_EPOLL)
132 75879 : tevent_epoll_init();
133 : #endif
134 :
135 75879 : tevent_standard_init();
136 : }
137 :
138 249213933 : const struct tevent_ops *tevent_find_ops_byname(const char *name)
139 : {
140 9162697 : struct tevent_ops_list *e;
141 :
142 249213933 : tevent_backend_init();
143 :
144 249213933 : if (name == NULL) {
145 83071290 : name = tevent_default_backend;
146 : }
147 249213933 : if (name == NULL) {
148 83071290 : name = "standard";
149 : }
150 :
151 581499201 : for (e = tevent_backends; e != NULL; e = e->next) {
152 581499201 : if (0 == strcmp(e->name, name)) {
153 249213933 : return e->ops;
154 : }
155 : }
156 :
157 0 : return NULL;
158 : }
159 :
160 : /*
161 : list available backends
162 : */
163 2363 : const char **tevent_backend_list(TALLOC_CTX *mem_ctx)
164 : {
165 2363 : const char **list = NULL;
166 128 : struct tevent_ops_list *e;
167 2363 : size_t idx = 0;
168 :
169 2363 : tevent_backend_init();
170 :
171 11815 : for (e=tevent_backends;e;e=e->next) {
172 9452 : idx += 1;
173 : }
174 :
175 2363 : list = talloc_zero_array(mem_ctx, const char *, idx+1);
176 2363 : if (list == NULL) {
177 0 : return NULL;
178 : }
179 :
180 2363 : idx = 0;
181 11815 : for (e=tevent_backends;e;e=e->next) {
182 9452 : list[idx] = talloc_strdup(list, e->name);
183 9452 : if (list[idx] == NULL) {
184 0 : TALLOC_FREE(list);
185 0 : return NULL;
186 : }
187 9452 : idx += 1;
188 : }
189 :
190 2235 : return list;
191 : }
192 :
193 : static void tevent_common_wakeup_fini(struct tevent_context *ev);
194 :
195 : #ifdef HAVE_PTHREAD
196 :
197 : static pthread_mutex_t tevent_contexts_mutex = PTHREAD_MUTEX_INITIALIZER;
198 : static struct tevent_context *tevent_contexts = NULL;
199 : static pthread_once_t tevent_atfork_initialized = PTHREAD_ONCE_INIT;
200 : static pid_t tevent_cached_global_pid = 0;
201 :
202 42764298 : static void tevent_atfork_prepare(void)
203 : {
204 261453 : struct tevent_context *ev;
205 261453 : int ret;
206 :
207 42764298 : ret = pthread_mutex_lock(&tevent_contexts_mutex);
208 42764298 : if (ret != 0) {
209 0 : abort();
210 : }
211 :
212 101393271 : for (ev = tevent_contexts; ev != NULL; ev = ev->next) {
213 523119 : struct tevent_threaded_context *tctx;
214 :
215 58634632 : for (tctx = ev->threaded_contexts; tctx != NULL;
216 5659 : tctx = tctx->next) {
217 5659 : ret = pthread_mutex_lock(&tctx->event_ctx_mutex);
218 5659 : if (ret != 0) {
219 0 : tevent_abort(ev, "pthread_mutex_lock failed");
220 : }
221 : }
222 :
223 58628973 : ret = pthread_mutex_lock(&ev->scheduled_mutex);
224 58628973 : if (ret != 0) {
225 0 : tevent_abort(ev, "pthread_mutex_lock failed");
226 : }
227 : }
228 42764298 : }
229 :
230 42699489 : static void tevent_atfork_parent(void)
231 : {
232 260409 : struct tevent_context *ev;
233 260409 : int ret;
234 :
235 101219114 : for (ev = DLIST_TAIL(tevent_contexts); ev != NULL;
236 58519619 : ev = DLIST_PREV(ev)) {
237 520987 : struct tevent_threaded_context *tctx;
238 :
239 58519619 : ret = pthread_mutex_unlock(&ev->scheduled_mutex);
240 58519619 : if (ret != 0) {
241 0 : tevent_abort(ev, "pthread_mutex_unlock failed");
242 : }
243 :
244 59046217 : for (tctx = DLIST_TAIL(ev->threaded_contexts); tctx != NULL;
245 5611 : tctx = DLIST_PREV(tctx)) {
246 5611 : ret = pthread_mutex_unlock(&tctx->event_ctx_mutex);
247 5611 : if (ret != 0) {
248 0 : tevent_abort(
249 : ev, "pthread_mutex_unlock failed");
250 : }
251 : }
252 : }
253 :
254 42699489 : ret = pthread_mutex_unlock(&tevent_contexts_mutex);
255 42699489 : if (ret != 0) {
256 0 : abort();
257 : }
258 42699489 : }
259 :
260 64809 : static void tevent_atfork_child(void)
261 : {
262 1044 : struct tevent_context *ev;
263 1044 : int ret;
264 :
265 64809 : tevent_cached_global_pid = getpid();
266 :
267 174166 : for (ev = DLIST_TAIL(tevent_contexts); ev != NULL;
268 109354 : ev = DLIST_PREV(ev)) {
269 2132 : struct tevent_threaded_context *tctx;
270 :
271 111534 : for (tctx = DLIST_TAIL(ev->threaded_contexts); tctx != NULL;
272 48 : tctx = DLIST_PREV(tctx)) {
273 48 : tctx->event_ctx = NULL;
274 :
275 48 : ret = pthread_mutex_unlock(&tctx->event_ctx_mutex);
276 48 : if (ret != 0) {
277 0 : tevent_abort(
278 : ev, "pthread_mutex_unlock failed");
279 : }
280 : }
281 :
282 109354 : ev->threaded_contexts = NULL;
283 :
284 109354 : ret = pthread_mutex_unlock(&ev->scheduled_mutex);
285 109354 : if (ret != 0) {
286 0 : tevent_abort(ev, "pthread_mutex_unlock failed");
287 : }
288 : }
289 :
290 64809 : ret = pthread_mutex_unlock(&tevent_contexts_mutex);
291 64809 : if (ret != 0) {
292 0 : abort();
293 : }
294 64809 : }
295 :
296 75799 : static void tevent_prep_atfork(void)
297 : {
298 1470 : int ret;
299 :
300 75799 : ret = pthread_atfork(tevent_atfork_prepare,
301 : tevent_atfork_parent,
302 : tevent_atfork_child);
303 75799 : if (ret != 0) {
304 0 : abort();
305 : }
306 :
307 75799 : tevent_cached_global_pid = getpid();
308 75799 : }
309 :
310 : #endif
311 :
312 433559614 : static int tevent_init_globals(void)
313 : {
314 : #ifdef HAVE_PTHREAD
315 22241609 : int ret;
316 :
317 436615621 : ret = pthread_once(&tevent_atfork_initialized, tevent_prep_atfork);
318 414374012 : if (ret != 0) {
319 0 : return ret;
320 : }
321 : #endif
322 :
323 411318005 : return 0;
324 : }
325 :
326 350393983 : _PUBLIC_ pid_t tevent_cached_getpid(void)
327 : {
328 : #ifdef HAVE_PTHREAD
329 350393983 : tevent_init_globals();
330 : #ifdef TEVENT_VERIFY_CACHED_GETPID
331 : if (tevent_cached_global_pid != getpid()) {
332 : tevent_abort(NULL, "tevent_cached_global_pid invalid");
333 : }
334 : #endif
335 350393981 : if (tevent_cached_global_pid != 0) {
336 331208381 : return tevent_cached_global_pid;
337 : }
338 : #endif
339 0 : return getpid();
340 : }
341 :
342 83140032 : int tevent_common_context_destructor(struct tevent_context *ev)
343 : {
344 3054220 : struct tevent_fd *fd, *fn;
345 3054220 : struct tevent_timer *te, *tn;
346 3054220 : struct tevent_immediate *ie, *in;
347 3054220 : struct tevent_signal *se, *sn;
348 3054220 : struct tevent_wrapper_glue *gl, *gn;
349 : #ifdef HAVE_PTHREAD
350 3054220 : int ret;
351 : #endif
352 :
353 83140032 : if (ev->wrapper.glue != NULL) {
354 0 : tevent_abort(ev,
355 : "tevent_common_context_destructor() active on wrapper");
356 : }
357 :
358 : #ifdef HAVE_PTHREAD
359 83140032 : ret = pthread_mutex_lock(&tevent_contexts_mutex);
360 83140032 : if (ret != 0) {
361 0 : abort();
362 : }
363 :
364 83140032 : DLIST_REMOVE(tevent_contexts, ev);
365 :
366 83140032 : ret = pthread_mutex_unlock(&tevent_contexts_mutex);
367 83140032 : if (ret != 0) {
368 0 : abort();
369 : }
370 :
371 98600277 : while (ev->threaded_contexts != NULL) {
372 72 : struct tevent_threaded_context *tctx = ev->threaded_contexts;
373 :
374 72 : ret = pthread_mutex_lock(&tctx->event_ctx_mutex);
375 72 : if (ret != 0) {
376 0 : abort();
377 : }
378 :
379 : /*
380 : * Indicate to the thread that the tevent_context is
381 : * gone. The counterpart of this is in
382 : * _tevent_threaded_schedule_immediate, there we read
383 : * this under the threaded_context's mutex.
384 : */
385 :
386 72 : tctx->event_ctx = NULL;
387 :
388 72 : ret = pthread_mutex_unlock(&tctx->event_ctx_mutex);
389 72 : if (ret != 0) {
390 0 : abort();
391 : }
392 :
393 3054299 : DLIST_REMOVE(ev->threaded_contexts, tctx);
394 : }
395 :
396 83140032 : ret = pthread_mutex_destroy(&ev->scheduled_mutex);
397 83140032 : if (ret != 0) {
398 0 : abort();
399 : }
400 : #endif
401 :
402 83140032 : for (gl = ev->wrapper.list; gl; gl = gn) {
403 0 : gn = gl->next;
404 :
405 0 : gl->main_ev = NULL;
406 0 : DLIST_REMOVE(ev->wrapper.list, gl);
407 : }
408 :
409 83140032 : tevent_common_wakeup_fini(ev);
410 :
411 84181773 : for (fd = ev->fd_events; fd; fd = fn) {
412 1041741 : fn = fd->next;
413 1041741 : tevent_common_fd_disarm(fd);
414 : }
415 :
416 83140032 : ev->last_zero_timer = NULL;
417 83328618 : for (te = ev->timer_events; te; te = tn) {
418 188586 : tn = te->next;
419 188586 : tevent_trace_timer_callback(te->event_ctx, te, TEVENT_EVENT_TRACE_DETACH);
420 188586 : te->wrapper = NULL;
421 188586 : te->event_ctx = NULL;
422 188586 : DLIST_REMOVE(ev->timer_events, te);
423 : }
424 :
425 83140740 : for (ie = ev->immediate_events; ie; ie = in) {
426 708 : in = ie->next;
427 708 : tevent_trace_immediate_callback(ie->event_ctx, ie, TEVENT_EVENT_TRACE_DETACH);
428 708 : ie->wrapper = NULL;
429 708 : ie->event_ctx = NULL;
430 708 : ie->cancel_fn = NULL;
431 708 : DLIST_REMOVE(ev->immediate_events, ie);
432 : }
433 :
434 83237724 : for (se = ev->signal_events; se; se = sn) {
435 97692 : sn = se->next;
436 97692 : tevent_trace_signal_callback(se->event_ctx, se, TEVENT_EVENT_TRACE_DETACH);
437 97692 : se->wrapper = NULL;
438 97692 : se->event_ctx = NULL;
439 97692 : DLIST_REMOVE(ev->signal_events, se);
440 : /*
441 : * This is important, Otherwise signals
442 : * are handled twice in child. eg, SIGHUP.
443 : * one added in parent, and another one in
444 : * the child. -- BoYang
445 : */
446 97692 : tevent_cleanup_pending_signal_handlers(se);
447 : }
448 :
449 : /* removing nesting hook or we get an abort when nesting is
450 : * not allowed. -- SSS
451 : * Note that we need to leave the allowed flag at its current
452 : * value, otherwise the use in tevent_re_initialise() will
453 : * leave the event context with allowed forced to false, which
454 : * will break users that expect nesting to be allowed
455 : */
456 83140032 : ev->nesting.level = 0;
457 83140032 : ev->nesting.hook_fn = NULL;
458 83140032 : ev->nesting.hook_private = NULL;
459 :
460 83140032 : return 0;
461 : }
462 :
463 83165631 : static int tevent_common_context_constructor(struct tevent_context *ev)
464 : {
465 3056007 : int ret;
466 :
467 83165631 : ret = tevent_init_globals();
468 83165631 : if (ret != 0) {
469 0 : return ret;
470 : }
471 :
472 : #ifdef HAVE_PTHREAD
473 :
474 83165631 : ret = pthread_mutex_init(&ev->scheduled_mutex, NULL);
475 83165633 : if (ret != 0) {
476 0 : return ret;
477 : }
478 :
479 83165633 : ret = pthread_mutex_lock(&tevent_contexts_mutex);
480 83165633 : if (ret != 0) {
481 0 : pthread_mutex_destroy(&ev->scheduled_mutex);
482 0 : return ret;
483 : }
484 :
485 83165633 : DLIST_ADD(tevent_contexts, ev);
486 :
487 83165633 : ret = pthread_mutex_unlock(&tevent_contexts_mutex);
488 83165633 : if (ret != 0) {
489 0 : abort();
490 : }
491 : #endif
492 :
493 83165633 : talloc_set_destructor(ev, tevent_common_context_destructor);
494 :
495 83165633 : return 0;
496 : }
497 :
498 139959790 : void tevent_common_check_double_free(TALLOC_CTX *ptr, const char *reason)
499 : {
500 139959790 : void *parent_ptr = talloc_parent(ptr);
501 139959790 : size_t parent_blocks = talloc_total_blocks(parent_ptr);
502 :
503 139959790 : if (parent_ptr != NULL && parent_blocks == 0) {
504 : /*
505 : * This is an implicit talloc free, as we still have a parent
506 : * but it's already being destroyed. Note that
507 : * talloc_total_blocks(ptr) also just returns 0 if a
508 : * talloc_free(ptr) is still in progress of freeing all
509 : * children.
510 : */
511 139281930 : return;
512 : }
513 :
514 0 : tevent_abort(NULL, reason);
515 : }
516 :
517 : /*
518 : create a event_context structure for a specific implementation.
519 : This must be the first events call, and all subsequent calls pass
520 : this event_context as the first element. Event handlers also
521 : receive this as their first argument.
522 :
523 : This function is for allowing third-party-applications to hook in gluecode
524 : to their own event loop code, so that they can make async usage of our client libs
525 :
526 : NOTE: use tevent_context_init() inside of samba!
527 : */
528 83071333 : struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx,
529 : const struct tevent_ops *ops,
530 : void *additional_data)
531 : {
532 3054253 : struct tevent_context *ev;
533 3054253 : int ret;
534 :
535 83071333 : ev = talloc_zero(mem_ctx, struct tevent_context);
536 83071331 : if (!ev) return NULL;
537 :
538 83071331 : ret = tevent_common_context_constructor(ev);
539 83071333 : if (ret != 0) {
540 0 : talloc_free(ev);
541 0 : return NULL;
542 : }
543 :
544 83071333 : ev->ops = ops;
545 83071333 : ev->additional_data = additional_data;
546 :
547 83071333 : ret = ev->ops->context_init(ev);
548 83071331 : if (ret != 0) {
549 0 : talloc_free(ev);
550 0 : return NULL;
551 : }
552 :
553 80017080 : return ev;
554 : }
555 :
556 : /*
557 : create a event_context structure. This must be the first events
558 : call, and all subsequent calls pass this event_context as the first
559 : element. Event handlers also receive this as their first argument.
560 : */
561 83071333 : struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx,
562 : const char *name)
563 : {
564 3054253 : const struct tevent_ops *ops;
565 :
566 83071333 : ops = tevent_find_ops_byname(name);
567 83071333 : if (ops == NULL) {
568 0 : return NULL;
569 : }
570 :
571 83071333 : return tevent_context_init_ops(mem_ctx, ops, NULL);
572 : }
573 :
574 :
575 : /*
576 : create a event_context structure. This must be the first events
577 : call, and all subsequent calls pass this event_context as the first
578 : element. Event handlers also receive this as their first argument.
579 : */
580 83071290 : struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx)
581 : {
582 83071290 : return tevent_context_init_byname(mem_ctx, NULL);
583 : }
584 :
585 : /*
586 : add a fd based event
587 : return NULL on failure (memory allocation error)
588 : */
589 15966371 : struct tevent_fd *_tevent_add_fd(struct tevent_context *ev,
590 : TALLOC_CTX *mem_ctx,
591 : int fd,
592 : uint16_t flags,
593 : tevent_fd_handler_t handler,
594 : void *private_data,
595 : const char *handler_name,
596 : const char *location)
597 : {
598 15966371 : return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data,
599 : handler_name, location);
600 : }
601 :
602 : /*
603 : set a close function on the fd event
604 : */
605 10213703 : void tevent_fd_set_close_fn(struct tevent_fd *fde,
606 : tevent_fd_close_fn_t close_fn)
607 : {
608 10213703 : if (!fde) return;
609 10213703 : if (!fde->event_ctx) return;
610 10213703 : fde->event_ctx->ops->set_fd_close_fn(fde, close_fn);
611 : }
612 :
613 9821728 : static void tevent_fd_auto_close_fn(struct tevent_context *ev,
614 : struct tevent_fd *fde,
615 : int fd,
616 : void *private_data)
617 : {
618 9821728 : close(fd);
619 9821728 : }
620 :
621 9856287 : void tevent_fd_set_auto_close(struct tevent_fd *fde)
622 : {
623 9856287 : tevent_fd_set_close_fn(fde, tevent_fd_auto_close_fn);
624 9856287 : }
625 :
626 : /*
627 : return the fd event flags
628 : */
629 40215582 : uint16_t tevent_fd_get_flags(struct tevent_fd *fde)
630 : {
631 40215582 : if (!fde) return 0;
632 39752944 : if (!fde->event_ctx) return 0;
633 38709795 : return fde->event_ctx->ops->get_fd_flags(fde);
634 : }
635 :
636 : /*
637 : set the fd event flags
638 : */
639 26081192 : void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags)
640 : {
641 26081192 : if (!fde) return;
642 26081192 : if (!fde->event_ctx) return;
643 26059132 : fde->event_ctx->ops->set_fd_flags(fde, flags);
644 : }
645 :
646 1 : bool tevent_signal_support(struct tevent_context *ev)
647 : {
648 1 : if (ev->ops->add_signal) {
649 1 : return true;
650 : }
651 0 : return false;
652 : }
653 :
654 : static void (*tevent_abort_fn)(const char *reason);
655 :
656 74513 : void tevent_set_abort_fn(void (*abort_fn)(const char *reason))
657 : {
658 74513 : tevent_abort_fn = abort_fn;
659 74513 : }
660 :
661 0 : void tevent_abort(struct tevent_context *ev, const char *reason)
662 : {
663 0 : if (ev != NULL) {
664 0 : tevent_debug(ev, TEVENT_DEBUG_FATAL,
665 : "abort: %s\n", reason);
666 : }
667 :
668 0 : if (!tevent_abort_fn) {
669 0 : abort();
670 : }
671 :
672 0 : tevent_abort_fn(reason);
673 0 : }
674 :
675 : /*
676 : add a timer event
677 : return NULL on failure
678 : */
679 417595133 : struct tevent_timer *_tevent_add_timer(struct tevent_context *ev,
680 : TALLOC_CTX *mem_ctx,
681 : struct timeval next_event,
682 : tevent_timer_handler_t handler,
683 : void *private_data,
684 : const char *handler_name,
685 : const char *location)
686 : {
687 417595133 : return ev->ops->add_timer(ev, mem_ctx, next_event, handler, private_data,
688 : handler_name, location);
689 : }
690 :
691 : /*
692 : allocate an immediate event
693 : return NULL on failure (memory allocation error)
694 : */
695 141279283 : struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx,
696 : const char *location)
697 : {
698 858166 : struct tevent_immediate *im;
699 :
700 141279283 : im = talloc(mem_ctx, struct tevent_immediate);
701 141279281 : if (im == NULL) return NULL;
702 :
703 141279281 : *im = (struct tevent_immediate) { .create_location = location };
704 :
705 141279281 : return im;
706 : }
707 :
708 : /*
709 : schedule an immediate event
710 : */
711 33317432 : void _tevent_schedule_immediate(struct tevent_immediate *im,
712 : struct tevent_context *ev,
713 : tevent_immediate_handler_t handler,
714 : void *private_data,
715 : const char *handler_name,
716 : const char *location)
717 : {
718 33317432 : ev->ops->schedule_immediate(im, ev, handler, private_data,
719 : handler_name, location);
720 33317432 : }
721 :
722 : /*
723 : add a signal event
724 :
725 : sa_flags are flags to sigaction(2)
726 :
727 : return NULL on failure
728 : */
729 254835 : struct tevent_signal *_tevent_add_signal(struct tevent_context *ev,
730 : TALLOC_CTX *mem_ctx,
731 : int signum,
732 : int sa_flags,
733 : tevent_signal_handler_t handler,
734 : void *private_data,
735 : const char *handler_name,
736 : const char *location)
737 : {
738 254835 : return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data,
739 : handler_name, location);
740 : }
741 :
742 81798487 : void tevent_loop_allow_nesting(struct tevent_context *ev)
743 : {
744 81798487 : if (ev->wrapper.glue != NULL) {
745 0 : tevent_abort(ev, "tevent_loop_allow_nesting() on wrapper");
746 0 : return;
747 : }
748 :
749 81798487 : if (ev->wrapper.list != NULL) {
750 0 : tevent_abort(ev, "tevent_loop_allow_nesting() with wrapper");
751 0 : return;
752 : }
753 :
754 81798487 : ev->nesting.allowed = true;
755 : }
756 :
757 1328 : void tevent_loop_set_nesting_hook(struct tevent_context *ev,
758 : tevent_nesting_hook hook,
759 : void *private_data)
760 : {
761 1328 : if (ev->nesting.hook_fn &&
762 1324 : (ev->nesting.hook_fn != hook ||
763 1324 : ev->nesting.hook_private != private_data)) {
764 : /* the way the nesting hook code is currently written
765 : we cannot support two different nesting hooks at the
766 : same time. */
767 0 : tevent_abort(ev, "tevent: Violation of nesting hook rules\n");
768 : }
769 1328 : ev->nesting.hook_fn = hook;
770 1328 : ev->nesting.hook_private = private_data;
771 1328 : }
772 :
773 0 : static void tevent_abort_nesting(struct tevent_context *ev, const char *location)
774 : {
775 0 : const char *reason;
776 :
777 0 : reason = talloc_asprintf(NULL, "tevent_loop_once() nesting at %s",
778 : location);
779 0 : if (!reason) {
780 0 : reason = "tevent_loop_once() nesting";
781 : }
782 :
783 0 : tevent_abort(ev, reason);
784 0 : }
785 :
786 : /*
787 : do a single event loop using the events defined in ev
788 : */
789 433677445 : int _tevent_loop_once(struct tevent_context *ev, const char *location)
790 : {
791 36706466 : int ret;
792 433677445 : void *nesting_stack_ptr = NULL;
793 :
794 433677445 : ev->nesting.level++;
795 :
796 433677445 : if (ev->nesting.level > 1) {
797 79147158 : if (!ev->nesting.allowed) {
798 0 : tevent_abort_nesting(ev, location);
799 0 : errno = ELOOP;
800 0 : return -1;
801 : }
802 : }
803 433677445 : if (ev->nesting.level > 0) {
804 433677445 : if (ev->nesting.hook_fn) {
805 0 : int ret2;
806 2950976 : ret2 = ev->nesting.hook_fn(ev,
807 : ev->nesting.hook_private,
808 : ev->nesting.level,
809 : true,
810 : (void *)&nesting_stack_ptr,
811 : location);
812 2950976 : if (ret2 != 0) {
813 0 : ret = ret2;
814 0 : goto done;
815 : }
816 : }
817 : }
818 :
819 433677445 : tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_LOOP_ONCE);
820 433677445 : ret = ev->ops->loop_once(ev, location);
821 433583162 : tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_LOOP_ONCE);
822 :
823 : /* New event (and request) will always start with call depth 0. */
824 433583162 : tevent_thread_call_depth_notify(TEVENT_CALL_FLOW_REQ_RESET,
825 : NULL,
826 : 0,
827 : __func__);
828 :
829 433583162 : if (ev->nesting.level > 0) {
830 433583162 : if (ev->nesting.hook_fn) {
831 0 : int ret2;
832 2950977 : ret2 = ev->nesting.hook_fn(ev,
833 : ev->nesting.hook_private,
834 : ev->nesting.level,
835 : false,
836 : (void *)&nesting_stack_ptr,
837 : location);
838 2950977 : if (ret2 != 0) {
839 0 : ret = ret2;
840 0 : goto done;
841 : }
842 : }
843 : }
844 :
845 433583162 : done:
846 433583162 : ev->nesting.level--;
847 433583162 : return ret;
848 : }
849 :
850 : /*
851 : this is a performance optimization for the samba4 nested event loop problems
852 : */
853 0 : int _tevent_loop_until(struct tevent_context *ev,
854 : bool (*finished)(void *private_data),
855 : void *private_data,
856 : const char *location)
857 : {
858 0 : int ret = 0;
859 0 : void *nesting_stack_ptr = NULL;
860 :
861 0 : ev->nesting.level++;
862 :
863 0 : if (ev->nesting.level > 1) {
864 0 : if (!ev->nesting.allowed) {
865 0 : tevent_abort_nesting(ev, location);
866 0 : errno = ELOOP;
867 0 : return -1;
868 : }
869 : }
870 0 : if (ev->nesting.level > 0) {
871 0 : if (ev->nesting.hook_fn) {
872 0 : int ret2;
873 0 : ret2 = ev->nesting.hook_fn(ev,
874 : ev->nesting.hook_private,
875 : ev->nesting.level,
876 : true,
877 : (void *)&nesting_stack_ptr,
878 : location);
879 0 : if (ret2 != 0) {
880 0 : ret = ret2;
881 0 : goto done;
882 : }
883 : }
884 : }
885 :
886 0 : while (!finished(private_data)) {
887 0 : tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_LOOP_ONCE);
888 0 : ret = ev->ops->loop_once(ev, location);
889 0 : tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_LOOP_ONCE);
890 0 : if (ret != 0) {
891 0 : break;
892 : }
893 : }
894 :
895 0 : if (ev->nesting.level > 0) {
896 0 : if (ev->nesting.hook_fn) {
897 0 : int ret2;
898 0 : ret2 = ev->nesting.hook_fn(ev,
899 : ev->nesting.hook_private,
900 : ev->nesting.level,
901 : false,
902 : (void *)&nesting_stack_ptr,
903 : location);
904 0 : if (ret2 != 0) {
905 0 : ret = ret2;
906 0 : goto done;
907 : }
908 : }
909 : }
910 :
911 0 : done:
912 0 : ev->nesting.level--;
913 0 : return ret;
914 : }
915 :
916 153232661 : bool tevent_common_have_events(struct tevent_context *ev)
917 : {
918 153232661 : if (ev->fd_events != NULL) {
919 153232657 : if (ev->fd_events != ev->wakeup_fde) {
920 152317071 : return true;
921 : }
922 41309 : if (ev->fd_events->next != NULL) {
923 41184 : return true;
924 : }
925 :
926 : /*
927 : * At this point we just have the wakeup pipe event as
928 : * the only fd_event. That one does not count as a
929 : * regular event, so look at the other event types.
930 : */
931 : }
932 :
933 32 : return ((ev->timer_events != NULL) ||
934 32 : (ev->immediate_events != NULL) ||
935 16 : (ev->signal_events != NULL));
936 : }
937 :
938 : /*
939 : return on failure or (with 0) if all fd events are removed
940 : */
941 94127 : int tevent_common_loop_wait(struct tevent_context *ev,
942 : const char *location)
943 : {
944 : /*
945 : * loop as long as we have events pending
946 : */
947 153232661 : while (tevent_common_have_events(ev)) {
948 874390 : int ret;
949 153232645 : ret = _tevent_loop_once(ev, location);
950 153138534 : if (ret != 0) {
951 0 : tevent_debug(ev, TEVENT_DEBUG_FATAL,
952 : "_tevent_loop_once() failed: %d - %s\n",
953 0 : ret, strerror(errno));
954 0 : return ret;
955 : }
956 : }
957 :
958 16 : tevent_debug(ev, TEVENT_DEBUG_WARNING,
959 : "tevent_common_loop_wait() out of events\n");
960 16 : return 0;
961 : }
962 :
963 : /*
964 : return on failure or (with 0) if all fd events are removed
965 : */
966 94127 : int _tevent_loop_wait(struct tevent_context *ev, const char *location)
967 : {
968 94127 : return ev->ops->loop_wait(ev, location);
969 : }
970 :
971 :
972 : /*
973 : re-initialise a tevent context. This leaves you with the same
974 : event context, but all events are wiped and the structure is
975 : re-initialised. This is most useful after a fork()
976 :
977 : zero is returned on success, non-zero on failure
978 : */
979 94300 : int tevent_re_initialise(struct tevent_context *ev)
980 : {
981 94300 : tevent_common_context_destructor(ev);
982 :
983 94300 : tevent_common_context_constructor(ev);
984 :
985 94300 : return ev->ops->context_init(ev);
986 : }
987 :
988 34307950 : static void wakeup_pipe_handler(struct tevent_context *ev,
989 : struct tevent_fd *fde,
990 : uint16_t flags, void *_private)
991 : {
992 1638338 : ssize_t ret;
993 :
994 1638338 : do {
995 : /*
996 : * This is the boilerplate for eventfd, but it works
997 : * for pipes too. And as we don't care about the data
998 : * we read, we're fine.
999 : */
1000 1638338 : uint64_t val;
1001 34307950 : ret = read(fde->fd, &val, sizeof(val));
1002 34307950 : } while (ret == -1 && errno == EINTR);
1003 34307950 : }
1004 :
1005 : /*
1006 : * Initialize the wakeup pipe and pipe fde
1007 : */
1008 :
1009 257915 : int tevent_common_wakeup_init(struct tevent_context *ev)
1010 : {
1011 4592 : int ret, read_fd;
1012 :
1013 257915 : if (ev->wakeup_fde != NULL) {
1014 143351 : return 0;
1015 : }
1016 :
1017 : #ifdef HAVE_EVENTFD
1018 111845 : ret = eventfd(0, EFD_NONBLOCK);
1019 111845 : if (ret == -1) {
1020 0 : return errno;
1021 : }
1022 111845 : read_fd = ev->wakeup_fd = ret;
1023 : #else
1024 : {
1025 : int pipe_fds[2];
1026 : ret = pipe(pipe_fds);
1027 : if (ret == -1) {
1028 : return errno;
1029 : }
1030 : ev->wakeup_fd = pipe_fds[1];
1031 : ev->wakeup_read_fd = pipe_fds[0];
1032 :
1033 : ev_set_blocking(ev->wakeup_fd, false);
1034 : ev_set_blocking(ev->wakeup_read_fd, false);
1035 :
1036 : read_fd = ev->wakeup_read_fd;
1037 : }
1038 : #endif
1039 :
1040 111845 : ev->wakeup_fde = tevent_add_fd(ev, ev, read_fd, TEVENT_FD_READ,
1041 : wakeup_pipe_handler, NULL);
1042 111845 : if (ev->wakeup_fde == NULL) {
1043 0 : close(ev->wakeup_fd);
1044 : #ifndef HAVE_EVENTFD
1045 : close(ev->wakeup_read_fd);
1046 : #endif
1047 0 : return ENOMEM;
1048 : }
1049 :
1050 109972 : return 0;
1051 : }
1052 :
1053 35707093 : int tevent_common_wakeup_fd(int fd)
1054 : {
1055 2964384 : ssize_t ret;
1056 :
1057 2964384 : do {
1058 : #ifdef HAVE_EVENTFD
1059 35707093 : uint64_t val = 1;
1060 35707093 : ret = write(fd, &val, sizeof(val));
1061 : #else
1062 : char c = '\0';
1063 : ret = write(fd, &c, 1);
1064 : #endif
1065 35707092 : } while ((ret == -1) && (errno == EINTR));
1066 :
1067 35707092 : return 0;
1068 : }
1069 :
1070 35470417 : int tevent_common_wakeup(struct tevent_context *ev)
1071 : {
1072 35470417 : if (ev->wakeup_fde == NULL) {
1073 0 : return ENOTCONN;
1074 : }
1075 :
1076 35470417 : return tevent_common_wakeup_fd(ev->wakeup_fd);
1077 : }
1078 :
1079 83140032 : static void tevent_common_wakeup_fini(struct tevent_context *ev)
1080 : {
1081 83140032 : if (ev->wakeup_fde == NULL) {
1082 79976663 : return;
1083 : }
1084 :
1085 111018 : TALLOC_FREE(ev->wakeup_fde);
1086 :
1087 111018 : close(ev->wakeup_fd);
1088 : #ifndef HAVE_EVENTFD
1089 : close(ev->wakeup_read_fd);
1090 : #endif
1091 : }
|