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 307368 : bool tevent_register_backend(const char *name, const struct tevent_ops *ops)
87 : {
88 6284 : struct tevent_ops_list *e;
89 :
90 768420 : for (e = tevent_backends; e != NULL; e = e->next) {
91 461052 : if (0 == strcmp(e->name, name)) {
92 : /* already registered, skip it */
93 0 : return true;
94 : }
95 : }
96 :
97 307368 : e = talloc(NULL, struct tevent_ops_list);
98 307368 : if (e == NULL) return false;
99 :
100 307368 : e->name = name;
101 307368 : e->ops = ops;
102 307368 : DLIST_ADD(tevent_backends, e);
103 :
104 301084 : 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 248975386 : static void tevent_backend_init(void)
120 : {
121 9325161 : static bool done;
122 :
123 248975386 : if (done) {
124 239574954 : return;
125 : }
126 :
127 76842 : done = true;
128 :
129 76842 : tevent_poll_init();
130 76842 : tevent_poll_mt_init();
131 : #if defined(HAVE_EPOLL)
132 76842 : tevent_epoll_init();
133 : #endif
134 :
135 76842 : tevent_standard_init();
136 : }
137 :
138 248973027 : const struct tevent_ops *tevent_find_ops_byname(const char *name)
139 : {
140 9325033 : struct tevent_ops_list *e;
141 :
142 248973027 : tevent_backend_init();
143 :
144 248973027 : if (name == NULL) {
145 82990988 : name = tevent_default_backend;
146 : }
147 248973027 : if (name == NULL) {
148 82990988 : name = "standard";
149 : }
150 :
151 580937087 : for (e = tevent_backends; e != NULL; e = e->next) {
152 580937087 : if (0 == strcmp(e->name, name)) {
153 248973027 : return e->ops;
154 : }
155 : }
156 :
157 0 : return NULL;
158 : }
159 :
160 : /*
161 : list available backends
162 : */
163 2359 : const char **tevent_backend_list(TALLOC_CTX *mem_ctx)
164 : {
165 2359 : const char **list = NULL;
166 128 : struct tevent_ops_list *e;
167 2359 : size_t idx = 0;
168 :
169 2359 : tevent_backend_init();
170 :
171 11795 : for (e=tevent_backends;e;e=e->next) {
172 9436 : idx += 1;
173 : }
174 :
175 2359 : list = talloc_zero_array(mem_ctx, const char *, idx+1);
176 2359 : if (list == NULL) {
177 0 : return NULL;
178 : }
179 :
180 2359 : idx = 0;
181 11795 : for (e=tevent_backends;e;e=e->next) {
182 9436 : list[idx] = talloc_strdup(list, e->name);
183 9436 : if (list[idx] == NULL) {
184 0 : TALLOC_FREE(list);
185 0 : return NULL;
186 : }
187 9436 : idx += 1;
188 : }
189 :
190 2231 : 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 43583719 : static void tevent_atfork_prepare(void)
203 : {
204 261735 : struct tevent_context *ev;
205 261735 : int ret;
206 :
207 43583719 : ret = pthread_mutex_lock(&tevent_contexts_mutex);
208 43583719 : if (ret != 0) {
209 0 : abort();
210 : }
211 :
212 102998552 : for (ev = tevent_contexts; ev != NULL; ev = ev->next) {
213 523615 : struct tevent_threaded_context *tctx;
214 :
215 59420763 : for (tctx = ev->threaded_contexts; tctx != NULL;
216 5930 : tctx = tctx->next) {
217 5930 : ret = pthread_mutex_lock(&tctx->event_ctx_mutex);
218 5930 : if (ret != 0) {
219 0 : tevent_abort(ev, "pthread_mutex_lock failed");
220 : }
221 : }
222 :
223 59414833 : ret = pthread_mutex_lock(&ev->scheduled_mutex);
224 59414833 : if (ret != 0) {
225 0 : tevent_abort(ev, "pthread_mutex_lock failed");
226 : }
227 : }
228 43583719 : }
229 :
230 43518219 : static void tevent_atfork_parent(void)
231 : {
232 260647 : struct tevent_context *ev;
233 260647 : int ret;
234 :
235 102822649 : for (ev = DLIST_TAIL(tevent_contexts); ev != NULL;
236 59304424 : ev = DLIST_PREV(ev)) {
237 521417 : struct tevent_threaded_context *tctx;
238 :
239 59304424 : ret = pthread_mutex_unlock(&ev->scheduled_mutex);
240 59304424 : if (ret != 0) {
241 0 : tevent_abort(ev, "pthread_mutex_unlock failed");
242 : }
243 :
244 59831723 : for (tctx = DLIST_TAIL(ev->threaded_contexts); tctx != NULL;
245 5882 : tctx = DLIST_PREV(tctx)) {
246 5882 : ret = pthread_mutex_unlock(&tctx->event_ctx_mutex);
247 5882 : if (ret != 0) {
248 0 : tevent_abort(
249 : ev, "pthread_mutex_unlock failed");
250 : }
251 : }
252 : }
253 :
254 43518219 : ret = pthread_mutex_unlock(&tevent_contexts_mutex);
255 43518219 : if (ret != 0) {
256 0 : abort();
257 : }
258 43518219 : }
259 :
260 65500 : static void tevent_atfork_child(void)
261 : {
262 1088 : struct tevent_context *ev;
263 1088 : int ret;
264 :
265 65500 : tevent_cached_global_pid = getpid();
266 :
267 175912 : for (ev = DLIST_TAIL(tevent_contexts); ev != NULL;
268 110409 : ev = DLIST_PREV(ev)) {
269 2198 : struct tevent_threaded_context *tctx;
270 :
271 112655 : 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 110409 : ev->threaded_contexts = NULL;
283 :
284 110409 : ret = pthread_mutex_unlock(&ev->scheduled_mutex);
285 110409 : if (ret != 0) {
286 0 : tevent_abort(ev, "pthread_mutex_unlock failed");
287 : }
288 : }
289 :
290 65500 : ret = pthread_mutex_unlock(&tevent_contexts_mutex);
291 65500 : if (ret != 0) {
292 0 : abort();
293 : }
294 65500 : }
295 :
296 76762 : static void tevent_prep_atfork(void)
297 : {
298 1565 : int ret;
299 :
300 76762 : ret = pthread_atfork(tevent_atfork_prepare,
301 : tevent_atfork_parent,
302 : tevent_atfork_child);
303 76762 : if (ret != 0) {
304 0 : abort();
305 : }
306 :
307 76762 : tevent_cached_global_pid = getpid();
308 76762 : }
309 :
310 : #endif
311 :
312 438359686 : static int tevent_init_globals(void)
313 : {
314 : #ifdef HAVE_PTHREAD
315 22345543 : int ret;
316 :
317 441469807 : ret = pthread_once(&tevent_atfork_initialized, tevent_prep_atfork);
318 419124264 : if (ret != 0) {
319 0 : return ret;
320 : }
321 : #endif
322 :
323 416014143 : return 0;
324 : }
325 :
326 355273176 : _PUBLIC_ pid_t tevent_cached_getpid(void)
327 : {
328 : #ifdef HAVE_PTHREAD
329 355273176 : 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 355273176 : if (tevent_cached_global_pid != 0) {
336 336037754 : return tevent_cached_global_pid;
337 : }
338 : #endif
339 0 : return getpid();
340 : }
341 :
342 83060697 : int tevent_common_context_destructor(struct tevent_context *ev)
343 : {
344 3108227 : struct tevent_fd *fd, *fn;
345 3108227 : struct tevent_timer *te, *tn;
346 3108227 : struct tevent_immediate *ie, *in;
347 3108227 : struct tevent_signal *se, *sn;
348 3108227 : struct tevent_wrapper_glue *gl, *gn;
349 : #ifdef HAVE_PTHREAD
350 3108227 : int ret;
351 : #endif
352 :
353 83060697 : 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 83060697 : ret = pthread_mutex_lock(&tevent_contexts_mutex);
360 83060697 : if (ret != 0) {
361 0 : abort();
362 : }
363 :
364 83060697 : DLIST_REMOVE(tevent_contexts, ev);
365 :
366 83060697 : ret = pthread_mutex_unlock(&tevent_contexts_mutex);
367 83060697 : if (ret != 0) {
368 0 : abort();
369 : }
370 :
371 98267334 : while (ev->threaded_contexts != NULL) {
372 75 : struct tevent_threaded_context *tctx = ev->threaded_contexts;
373 :
374 75 : ret = pthread_mutex_lock(&tctx->event_ctx_mutex);
375 75 : 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 75 : tctx->event_ctx = NULL;
387 :
388 75 : ret = pthread_mutex_unlock(&tctx->event_ctx_mutex);
389 75 : if (ret != 0) {
390 0 : abort();
391 : }
392 :
393 3108309 : DLIST_REMOVE(ev->threaded_contexts, tctx);
394 : }
395 :
396 83060697 : ret = pthread_mutex_destroy(&ev->scheduled_mutex);
397 83060697 : if (ret != 0) {
398 0 : abort();
399 : }
400 : #endif
401 :
402 83060697 : 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 83060697 : tevent_common_wakeup_fini(ev);
410 :
411 84129183 : for (fd = ev->fd_events; fd; fd = fn) {
412 1068486 : fn = fd->next;
413 1068486 : tevent_common_fd_disarm(fd);
414 : }
415 :
416 83060697 : ev->last_zero_timer = NULL;
417 83251805 : for (te = ev->timer_events; te; te = tn) {
418 191108 : tn = te->next;
419 191108 : tevent_trace_timer_callback(te->event_ctx, te, TEVENT_EVENT_TRACE_DETACH);
420 191108 : te->wrapper = NULL;
421 191108 : te->event_ctx = NULL;
422 191108 : DLIST_REMOVE(ev->timer_events, te);
423 : }
424 :
425 83061408 : for (ie = ev->immediate_events; ie; ie = in) {
426 711 : in = ie->next;
427 711 : tevent_trace_immediate_callback(ie->event_ctx, ie, TEVENT_EVENT_TRACE_DETACH);
428 711 : ie->wrapper = NULL;
429 711 : ie->event_ctx = NULL;
430 711 : ie->cancel_fn = NULL;
431 711 : DLIST_REMOVE(ev->immediate_events, ie);
432 : }
433 :
434 83158917 : for (se = ev->signal_events; se; se = sn) {
435 98220 : sn = se->next;
436 98220 : tevent_trace_signal_callback(se->event_ctx, se, TEVENT_EVENT_TRACE_DETACH);
437 98220 : se->wrapper = NULL;
438 98220 : se->event_ctx = NULL;
439 98220 : 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 98220 : 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 83060697 : ev->nesting.level = 0;
457 83060697 : ev->nesting.hook_fn = NULL;
458 83060697 : ev->nesting.hook_private = NULL;
459 :
460 83060697 : return 0;
461 : }
462 :
463 83086510 : static int tevent_common_context_constructor(struct tevent_context *ev)
464 : {
465 3110121 : int ret;
466 :
467 83086510 : ret = tevent_init_globals();
468 83086510 : if (ret != 0) {
469 0 : return ret;
470 : }
471 :
472 : #ifdef HAVE_PTHREAD
473 :
474 83086510 : ret = pthread_mutex_init(&ev->scheduled_mutex, NULL);
475 83086510 : if (ret != 0) {
476 0 : return ret;
477 : }
478 :
479 83086510 : ret = pthread_mutex_lock(&tevent_contexts_mutex);
480 83086510 : if (ret != 0) {
481 0 : pthread_mutex_destroy(&ev->scheduled_mutex);
482 0 : return ret;
483 : }
484 :
485 83086510 : DLIST_ADD(tevent_contexts, ev);
486 :
487 83086510 : ret = pthread_mutex_unlock(&tevent_contexts_mutex);
488 83086510 : if (ret != 0) {
489 0 : abort();
490 : }
491 : #endif
492 :
493 83086510 : talloc_set_destructor(ev, tevent_common_context_destructor);
494 :
495 83086510 : return 0;
496 : }
497 :
498 139638926 : void tevent_common_check_double_free(TALLOC_CTX *ptr, const char *reason)
499 : {
500 139638926 : void *parent_ptr = talloc_parent(ptr);
501 139638926 : size_t parent_blocks = talloc_total_blocks(parent_ptr);
502 :
503 139638926 : 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 138950623 : 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 82991031 : struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx,
529 : const struct tevent_ops *ops,
530 : void *additional_data)
531 : {
532 3108365 : struct tevent_context *ev;
533 3108365 : int ret;
534 :
535 82991031 : ev = talloc_zero(mem_ctx, struct tevent_context);
536 82991031 : if (!ev) return NULL;
537 :
538 82991031 : ret = tevent_common_context_constructor(ev);
539 82991031 : if (ret != 0) {
540 0 : talloc_free(ev);
541 0 : return NULL;
542 : }
543 :
544 82991031 : ev->ops = ops;
545 82991031 : ev->additional_data = additional_data;
546 :
547 82991031 : ret = ev->ops->context_init(ev);
548 82991031 : if (ret != 0) {
549 0 : talloc_free(ev);
550 0 : return NULL;
551 : }
552 :
553 79882666 : 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 82991031 : struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx,
562 : const char *name)
563 : {
564 3108365 : const struct tevent_ops *ops;
565 :
566 82991031 : ops = tevent_find_ops_byname(name);
567 82991031 : if (ops == NULL) {
568 0 : return NULL;
569 : }
570 :
571 82991031 : 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 82990988 : struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx)
581 : {
582 82990988 : 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 16091455 : 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 16091455 : 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 10240215 : void tevent_fd_set_close_fn(struct tevent_fd *fde,
606 : tevent_fd_close_fn_t close_fn)
607 : {
608 10240215 : if (!fde) return;
609 10240215 : if (!fde->event_ctx) return;
610 10240215 : fde->event_ctx->ops->set_fd_close_fn(fde, close_fn);
611 : }
612 :
613 9842521 : 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 9842521 : close(fd);
619 9842521 : }
620 :
621 9877162 : void tevent_fd_set_auto_close(struct tevent_fd *fde)
622 : {
623 9877162 : tevent_fd_set_close_fn(fde, tevent_fd_auto_close_fn);
624 9877162 : }
625 :
626 : /*
627 : return the fd event flags
628 : */
629 39902080 : uint16_t tevent_fd_get_flags(struct tevent_fd *fde)
630 : {
631 39902080 : if (!fde) return 0;
632 39412374 : if (!fde->event_ctx) return 0;
633 38368968 : return fde->event_ctx->ops->get_fd_flags(fde);
634 : }
635 :
636 : /*
637 : set the fd event flags
638 : */
639 25885542 : void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags)
640 : {
641 25885542 : if (!fde) return;
642 25885542 : if (!fde->event_ctx) return;
643 25863379 : 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 75587 : void tevent_set_abort_fn(void (*abort_fn)(const char *reason))
657 : {
658 75587 : tevent_abort_fn = abort_fn;
659 75587 : }
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 419917174 : 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 419917174 : 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 141049707 : struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx,
696 : const char *location)
697 : {
698 869800 : struct tevent_immediate *im;
699 :
700 141049707 : im = talloc(mem_ctx, struct tevent_immediate);
701 141049705 : if (im == NULL) return NULL;
702 :
703 141049705 : *im = (struct tevent_immediate) { .create_location = location };
704 :
705 141049705 : return im;
706 : }
707 :
708 : /*
709 : schedule an immediate event
710 : */
711 33290102 : 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 33290102 : ev->ops->schedule_immediate(im, ev, handler, private_data,
719 : handler_name, location);
720 33290102 : }
721 :
722 : /*
723 : add a signal event
724 :
725 : sa_flags are flags to sigaction(2)
726 :
727 : return NULL on failure
728 : */
729 257925 : 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 257925 : return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data,
739 : handler_name, location);
740 : }
741 :
742 81708898 : void tevent_loop_allow_nesting(struct tevent_context *ev)
743 : {
744 81708898 : if (ev->wrapper.glue != NULL) {
745 0 : tevent_abort(ev, "tevent_loop_allow_nesting() on wrapper");
746 0 : return;
747 : }
748 :
749 81708898 : if (ev->wrapper.list != NULL) {
750 0 : tevent_abort(ev, "tevent_loop_allow_nesting() with wrapper");
751 0 : return;
752 : }
753 :
754 81708898 : 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 438539046 : int _tevent_loop_once(struct tevent_context *ev, const char *location)
790 : {
791 36745278 : int ret;
792 438539046 : void *nesting_stack_ptr = NULL;
793 :
794 438539046 : ev->nesting.level++;
795 :
796 438539046 : if (ev->nesting.level > 1) {
797 81355984 : if (!ev->nesting.allowed) {
798 0 : tevent_abort_nesting(ev, location);
799 0 : errno = ELOOP;
800 0 : return -1;
801 : }
802 : }
803 438539046 : if (ev->nesting.level > 0) {
804 438539046 : if (ev->nesting.hook_fn) {
805 0 : int ret2;
806 2954453 : 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 2954453 : if (ret2 != 0) {
813 0 : ret = ret2;
814 0 : goto done;
815 : }
816 : }
817 : }
818 :
819 438539046 : tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_LOOP_ONCE);
820 438539046 : ret = ev->ops->loop_once(ev, location);
821 438443579 : tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_LOOP_ONCE);
822 :
823 : /* New event (and request) will always start with call depth 0. */
824 438443579 : tevent_thread_call_depth_notify(TEVENT_CALL_FLOW_REQ_RESET,
825 : NULL,
826 : 0,
827 : __func__);
828 :
829 438443579 : if (ev->nesting.level > 0) {
830 438443579 : if (ev->nesting.hook_fn) {
831 0 : int ret2;
832 2954454 : 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 2954454 : if (ret2 != 0) {
839 0 : ret = ret2;
840 0 : goto done;
841 : }
842 : }
843 : }
844 :
845 438443579 : done:
846 438443579 : ev->nesting.level--;
847 438443579 : 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 155398385 : bool tevent_common_have_events(struct tevent_context *ev)
917 : {
918 155398385 : if (ev->fd_events != NULL) {
919 155398381 : if (ev->fd_events != ev->wakeup_fde) {
920 154482012 : return true;
921 : }
922 37182 : if (ev->fd_events->next != NULL) {
923 37057 : 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 95297 : 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 155398385 : while (tevent_common_have_events(ev)) {
948 879300 : int ret;
949 155398369 : ret = _tevent_loop_once(ev, location);
950 155303088 : 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 95297 : int _tevent_loop_wait(struct tevent_context *ev, const char *location)
967 : {
968 95297 : 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 95479 : int tevent_re_initialise(struct tevent_context *ev)
980 : {
981 95479 : tevent_common_context_destructor(ev);
982 :
983 95479 : tevent_common_context_constructor(ev);
984 :
985 95479 : return ev->ops->context_init(ev);
986 : }
987 :
988 35145848 : static void wakeup_pipe_handler(struct tevent_context *ev,
989 : struct tevent_fd *fde,
990 : uint16_t flags, void *_private)
991 : {
992 1633024 : ssize_t ret;
993 :
994 1633024 : 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 1633024 : uint64_t val;
1001 35145848 : ret = read(fde->fd, &val, sizeof(val));
1002 35145848 : } while (ret == -1 && errno == EINTR);
1003 35145848 : }
1004 :
1005 : /*
1006 : * Initialize the wakeup pipe and pipe fde
1007 : */
1008 :
1009 261138 : int tevent_common_wakeup_init(struct tevent_context *ev)
1010 : {
1011 4592 : int ret, read_fd;
1012 :
1013 261138 : if (ev->wakeup_fde != NULL) {
1014 145283 : return 0;
1015 : }
1016 :
1017 : #ifdef HAVE_EVENTFD
1018 113136 : ret = eventfd(0, EFD_NONBLOCK);
1019 113136 : if (ret == -1) {
1020 0 : return errno;
1021 : }
1022 113136 : 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 113136 : ev->wakeup_fde = tevent_add_fd(ev, ev, read_fd, TEVENT_FD_READ,
1041 : wakeup_pipe_handler, NULL);
1042 113136 : 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 111263 : return 0;
1051 : }
1052 :
1053 36518163 : int tevent_common_wakeup_fd(int fd)
1054 : {
1055 2951269 : ssize_t ret;
1056 :
1057 2951269 : do {
1058 : #ifdef HAVE_EVENTFD
1059 36518163 : uint64_t val = 1;
1060 36518163 : ret = write(fd, &val, sizeof(val));
1061 : #else
1062 : char c = '\0';
1063 : ret = write(fd, &c, 1);
1064 : #endif
1065 36518161 : } while ((ret == -1) && (errno == EINTR));
1066 :
1067 36518161 : return 0;
1068 : }
1069 :
1070 36280782 : int tevent_common_wakeup(struct tevent_context *ev)
1071 : {
1072 36280782 : if (ev->wakeup_fde == NULL) {
1073 0 : return ENOTCONN;
1074 : }
1075 :
1076 36280782 : return tevent_common_wakeup_fd(ev->wakeup_fd);
1077 : }
1078 :
1079 83060697 : static void tevent_common_wakeup_fini(struct tevent_context *ev)
1080 : {
1081 83060697 : if (ev->wakeup_fde == NULL) {
1082 79842062 : return;
1083 : }
1084 :
1085 112277 : TALLOC_FREE(ev->wakeup_fde);
1086 :
1087 112277 : close(ev->wakeup_fd);
1088 : #ifndef HAVE_EVENTFD
1089 : close(ev->wakeup_read_fd);
1090 : #endif
1091 : }
|