tevent: Factor out context initialization
[sfrench/samba-autobuild/.git] / lib / tevent / tevent.c
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 static void tevent_abort(struct tevent_context *ev, const char *reason);
74
75 struct tevent_ops_list {
76         struct tevent_ops_list *next, *prev;
77         const char *name;
78         const struct tevent_ops *ops;
79 };
80
81 /* list of registered event backends */
82 static struct tevent_ops_list *tevent_backends = NULL;
83 static char *tevent_default_backend = NULL;
84
85 /*
86   register an events backend
87 */
88 bool tevent_register_backend(const char *name, const struct tevent_ops *ops)
89 {
90         struct tevent_ops_list *e;
91
92         for (e = tevent_backends; e != NULL; e = e->next) {
93                 if (0 == strcmp(e->name, name)) {
94                         /* already registered, skip it */
95                         return true;
96                 }
97         }
98
99         e = talloc(NULL, struct tevent_ops_list);
100         if (e == NULL) return false;
101
102         e->name = name;
103         e->ops = ops;
104         DLIST_ADD(tevent_backends, e);
105
106         return true;
107 }
108
109 /*
110   set the default event backend
111  */
112 void tevent_set_default_backend(const char *backend)
113 {
114         talloc_free(tevent_default_backend);
115         tevent_default_backend = talloc_strdup(NULL, backend);
116 }
117
118 /*
119   initialise backends if not already done
120 */
121 static void tevent_backend_init(void)
122 {
123         static bool done;
124
125         if (done) {
126                 return;
127         }
128
129         done = true;
130
131         tevent_select_init();
132         tevent_poll_init();
133         tevent_poll_mt_init();
134 #if defined(HAVE_EPOLL)
135         tevent_epoll_init();
136 #elif defined(HAVE_SOLARIS_PORTS)
137         tevent_port_init();
138 #endif
139
140         tevent_standard_init();
141 }
142
143 _PRIVATE_ const struct tevent_ops *tevent_find_ops_byname(const char *name)
144 {
145         struct tevent_ops_list *e;
146
147         tevent_backend_init();
148
149         if (name == NULL) {
150                 name = tevent_default_backend;
151         }
152         if (name == NULL) {
153                 name = "standard";
154         }
155
156         for (e = tevent_backends; e != NULL; e = e->next) {
157                 if (0 == strcmp(e->name, name)) {
158                         return e->ops;
159                 }
160         }
161
162         return NULL;
163 }
164
165 /*
166   list available backends
167 */
168 const char **tevent_backend_list(TALLOC_CTX *mem_ctx)
169 {
170         const char **list = NULL;
171         struct tevent_ops_list *e;
172
173         tevent_backend_init();
174
175         for (e=tevent_backends;e;e=e->next) {
176                 list = ev_str_list_add(list, e->name);
177         }
178
179         talloc_steal(mem_ctx, list);
180
181         return list;
182 }
183
184 static void tevent_common_wakeup_fini(struct tevent_context *ev);
185
186 #ifdef HAVE_PTHREAD
187
188 static pthread_mutex_t tevent_contexts_mutex = PTHREAD_MUTEX_INITIALIZER;
189 static struct tevent_context *tevent_contexts = NULL;
190 static pthread_once_t tevent_atfork_initialized = PTHREAD_ONCE_INIT;
191
192 static void tevent_atfork_prepare(void)
193 {
194         struct tevent_context *ev;
195         int ret;
196
197         ret = pthread_mutex_lock(&tevent_contexts_mutex);
198         if (ret != 0) {
199                 abort();
200         }
201
202         for (ev = tevent_contexts; ev != NULL; ev = ev->next) {
203                 struct tevent_threaded_context *tctx;
204
205                 for (tctx = ev->threaded_contexts; tctx != NULL;
206                      tctx = tctx->next) {
207                         ret = pthread_mutex_lock(&tctx->event_ctx_mutex);
208                         if (ret != 0) {
209                                 tevent_abort(ev, "pthread_mutex_lock failed");
210                         }
211                 }
212
213                 ret = pthread_mutex_lock(&ev->scheduled_mutex);
214                 if (ret != 0) {
215                         tevent_abort(ev, "pthread_mutex_lock failed");
216                 }
217         }
218 }
219
220 static void tevent_atfork_parent(void)
221 {
222         struct tevent_context *ev;
223         int ret;
224
225         for (ev = DLIST_TAIL(tevent_contexts); ev != NULL;
226              ev = DLIST_PREV(ev)) {
227                 struct tevent_threaded_context *tctx;
228
229                 ret = pthread_mutex_unlock(&ev->scheduled_mutex);
230                 if (ret != 0) {
231                         tevent_abort(ev, "pthread_mutex_unlock failed");
232                 }
233
234                 for (tctx = DLIST_TAIL(ev->threaded_contexts); tctx != NULL;
235                      tctx = DLIST_PREV(tctx)) {
236                         ret = pthread_mutex_unlock(&tctx->event_ctx_mutex);
237                         if (ret != 0) {
238                                 tevent_abort(
239                                         ev, "pthread_mutex_unlock failed");
240                         }
241                 }
242         }
243
244         ret = pthread_mutex_unlock(&tevent_contexts_mutex);
245         if (ret != 0) {
246                 abort();
247         }
248 }
249
250 static void tevent_atfork_child(void)
251 {
252         struct tevent_context *ev;
253         int ret;
254
255         for (ev = DLIST_TAIL(tevent_contexts); ev != NULL;
256              ev = DLIST_PREV(ev)) {
257                 struct tevent_threaded_context *tctx;
258
259                 for (tctx = DLIST_TAIL(ev->threaded_contexts); tctx != NULL;
260                      tctx = DLIST_PREV(tctx)) {
261                         tctx->event_ctx = NULL;
262
263                         ret = pthread_mutex_unlock(&tctx->event_ctx_mutex);
264                         if (ret != 0) {
265                                 tevent_abort(
266                                         ev, "pthread_mutex_unlock failed");
267                         }
268                 }
269
270                 ev->threaded_contexts = NULL;
271
272                 ret = pthread_mutex_unlock(&ev->scheduled_mutex);
273                 if (ret != 0) {
274                         tevent_abort(ev, "pthread_mutex_unlock failed");
275                 }
276         }
277
278         ret = pthread_mutex_unlock(&tevent_contexts_mutex);
279         if (ret != 0) {
280                 abort();
281         }
282 }
283
284 static void tevent_prep_atfork(void)
285 {
286         int ret;
287
288         ret = pthread_atfork(tevent_atfork_prepare,
289                              tevent_atfork_parent,
290                              tevent_atfork_child);
291         if (ret != 0) {
292                 abort();
293         }
294 }
295
296 #endif
297
298 int tevent_common_context_destructor(struct tevent_context *ev)
299 {
300         struct tevent_fd *fd, *fn;
301         struct tevent_timer *te, *tn;
302         struct tevent_immediate *ie, *in;
303         struct tevent_signal *se, *sn;
304
305 #ifdef HAVE_PTHREAD
306         int ret;
307
308         ret = pthread_mutex_lock(&tevent_contexts_mutex);
309         if (ret != 0) {
310                 abort();
311         }
312
313         DLIST_REMOVE(tevent_contexts, ev);
314
315         ret = pthread_mutex_unlock(&tevent_contexts_mutex);
316         if (ret != 0) {
317                 abort();
318         }
319
320         while (ev->threaded_contexts != NULL) {
321                 struct tevent_threaded_context *tctx = ev->threaded_contexts;
322
323                 ret = pthread_mutex_lock(&tctx->event_ctx_mutex);
324                 if (ret != 0) {
325                         abort();
326                 }
327
328                 /*
329                  * Indicate to the thread that the tevent_context is
330                  * gone. The counterpart of this is in
331                  * _tevent_threaded_schedule_immediate, there we read
332                  * this under the threaded_context's mutex.
333                  */
334
335                 tctx->event_ctx = NULL;
336
337                 ret = pthread_mutex_unlock(&tctx->event_ctx_mutex);
338                 if (ret != 0) {
339                         abort();
340                 }
341
342                 DLIST_REMOVE(ev->threaded_contexts, tctx);
343         }
344 #endif
345
346         tevent_common_wakeup_fini(ev);
347
348         for (fd = ev->fd_events; fd; fd = fn) {
349                 fn = fd->next;
350                 fd->event_ctx = NULL;
351                 DLIST_REMOVE(ev->fd_events, fd);
352         }
353
354         ev->last_zero_timer = NULL;
355         for (te = ev->timer_events; te; te = tn) {
356                 tn = te->next;
357                 te->event_ctx = NULL;
358                 DLIST_REMOVE(ev->timer_events, te);
359         }
360
361         for (ie = ev->immediate_events; ie; ie = in) {
362                 in = ie->next;
363                 ie->event_ctx = NULL;
364                 ie->cancel_fn = NULL;
365                 DLIST_REMOVE(ev->immediate_events, ie);
366         }
367
368         for (se = ev->signal_events; se; se = sn) {
369                 sn = se->next;
370                 se->event_ctx = NULL;
371                 DLIST_REMOVE(ev->signal_events, se);
372                 /*
373                  * This is important, Otherwise signals
374                  * are handled twice in child. eg, SIGHUP.
375                  * one added in parent, and another one in
376                  * the child. -- BoYang
377                  */
378                 tevent_cleanup_pending_signal_handlers(se);
379         }
380
381         /* removing nesting hook or we get an abort when nesting is
382          * not allowed. -- SSS
383          * Note that we need to leave the allowed flag at its current
384          * value, otherwise the use in tevent_re_initialise() will
385          * leave the event context with allowed forced to false, which
386          * will break users that expect nesting to be allowed
387          */
388         ev->nesting.level = 0;
389         ev->nesting.hook_fn = NULL;
390         ev->nesting.hook_private = NULL;
391
392         return 0;
393 }
394
395 static int tevent_common_context_constructor(struct tevent_context *ev)
396 {
397         int ret;
398
399 #ifdef HAVE_PTHREAD
400
401         ret = pthread_once(&tevent_atfork_initialized, tevent_prep_atfork);
402         if (ret != 0) {
403                 return ret;
404         }
405
406         ret = pthread_mutex_init(&ev->scheduled_mutex, NULL);
407         if (ret != 0) {
408                 return ret;
409         }
410
411         ret = pthread_mutex_lock(&tevent_contexts_mutex);
412         if (ret != 0) {
413                 pthread_mutex_destroy(&ev->scheduled_mutex);
414                 return ret;
415         }
416
417         DLIST_ADD(tevent_contexts, ev);
418
419         ret = pthread_mutex_unlock(&tevent_contexts_mutex);
420         if (ret != 0) {
421                 abort();
422         }
423 #endif
424
425         talloc_set_destructor(ev, tevent_common_context_destructor);
426
427         return 0;
428 }
429
430 /*
431   create a event_context structure for a specific implemementation.
432   This must be the first events call, and all subsequent calls pass
433   this event_context as the first element. Event handlers also
434   receive this as their first argument.
435
436   This function is for allowing third-party-applications to hook in gluecode
437   to their own event loop code, so that they can make async usage of our client libs
438
439   NOTE: use tevent_context_init() inside of samba!
440 */
441 struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx,
442                                                const struct tevent_ops *ops,
443                                                void *additional_data)
444 {
445         struct tevent_context *ev;
446         int ret;
447
448         ev = talloc_zero(mem_ctx, struct tevent_context);
449         if (!ev) return NULL;
450
451         ret = tevent_common_context_constructor(ev);
452         if (ret != 0) {
453                 talloc_free(ev);
454                 return NULL;
455         }
456
457         ev->ops = ops;
458         ev->additional_data = additional_data;
459
460         ret = ev->ops->context_init(ev);
461         if (ret != 0) {
462                 talloc_free(ev);
463                 return NULL;
464         }
465
466         return ev;
467 }
468
469 /*
470   create a event_context structure. This must be the first events
471   call, and all subsequent calls pass this event_context as the first
472   element. Event handlers also receive this as their first argument.
473 */
474 struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx,
475                                                   const char *name)
476 {
477         const struct tevent_ops *ops;
478
479         ops = tevent_find_ops_byname(name);
480         if (ops == NULL) {
481                 return NULL;
482         }
483
484         return tevent_context_init_ops(mem_ctx, ops, NULL);
485 }
486
487
488 /*
489   create a event_context structure. This must be the first events
490   call, and all subsequent calls pass this event_context as the first
491   element. Event handlers also receive this as their first argument.
492 */
493 struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx)
494 {
495         return tevent_context_init_byname(mem_ctx, NULL);
496 }
497
498 /*
499   add a fd based event
500   return NULL on failure (memory allocation error)
501 */
502 struct tevent_fd *_tevent_add_fd(struct tevent_context *ev,
503                                  TALLOC_CTX *mem_ctx,
504                                  int fd,
505                                  uint16_t flags,
506                                  tevent_fd_handler_t handler,
507                                  void *private_data,
508                                  const char *handler_name,
509                                  const char *location)
510 {
511         return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data,
512                                handler_name, location);
513 }
514
515 /*
516   set a close function on the fd event
517 */
518 void tevent_fd_set_close_fn(struct tevent_fd *fde,
519                             tevent_fd_close_fn_t close_fn)
520 {
521         if (!fde) return;
522         if (!fde->event_ctx) return;
523         fde->event_ctx->ops->set_fd_close_fn(fde, close_fn);
524 }
525
526 static void tevent_fd_auto_close_fn(struct tevent_context *ev,
527                                     struct tevent_fd *fde,
528                                     int fd,
529                                     void *private_data)
530 {
531         close(fd);
532 }
533
534 void tevent_fd_set_auto_close(struct tevent_fd *fde)
535 {
536         tevent_fd_set_close_fn(fde, tevent_fd_auto_close_fn);
537 }
538
539 /*
540   return the fd event flags
541 */
542 uint16_t tevent_fd_get_flags(struct tevent_fd *fde)
543 {
544         if (!fde) return 0;
545         if (!fde->event_ctx) return 0;
546         return fde->event_ctx->ops->get_fd_flags(fde);
547 }
548
549 /*
550   set the fd event flags
551 */
552 void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags)
553 {
554         if (!fde) return;
555         if (!fde->event_ctx) return;
556         fde->event_ctx->ops->set_fd_flags(fde, flags);
557 }
558
559 bool tevent_signal_support(struct tevent_context *ev)
560 {
561         if (ev->ops->add_signal) {
562                 return true;
563         }
564         return false;
565 }
566
567 static void (*tevent_abort_fn)(const char *reason);
568
569 void tevent_set_abort_fn(void (*abort_fn)(const char *reason))
570 {
571         tevent_abort_fn = abort_fn;
572 }
573
574 static void tevent_abort(struct tevent_context *ev, const char *reason)
575 {
576         tevent_debug(ev, TEVENT_DEBUG_FATAL,
577                      "abort: %s\n", reason);
578
579         if (!tevent_abort_fn) {
580                 abort();
581         }
582
583         tevent_abort_fn(reason);
584 }
585
586 /*
587   add a timer event
588   return NULL on failure
589 */
590 struct tevent_timer *_tevent_add_timer(struct tevent_context *ev,
591                                        TALLOC_CTX *mem_ctx,
592                                        struct timeval next_event,
593                                        tevent_timer_handler_t handler,
594                                        void *private_data,
595                                        const char *handler_name,
596                                        const char *location)
597 {
598         return ev->ops->add_timer(ev, mem_ctx, next_event, handler, private_data,
599                                   handler_name, location);
600 }
601
602 /*
603   allocate an immediate event
604   return NULL on failure (memory allocation error)
605 */
606 struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx,
607                                                   const char *location)
608 {
609         struct tevent_immediate *im;
610
611         im = talloc(mem_ctx, struct tevent_immediate);
612         if (im == NULL) return NULL;
613
614         im->prev                = NULL;
615         im->next                = NULL;
616         im->event_ctx           = NULL;
617         im->create_location     = location;
618         im->handler             = NULL;
619         im->private_data        = NULL;
620         im->handler_name        = NULL;
621         im->schedule_location   = NULL;
622         im->cancel_fn           = NULL;
623         im->additional_data     = NULL;
624
625         return im;
626 }
627
628 /*
629   schedule an immediate event
630 */
631 void _tevent_schedule_immediate(struct tevent_immediate *im,
632                                 struct tevent_context *ev,
633                                 tevent_immediate_handler_t handler,
634                                 void *private_data,
635                                 const char *handler_name,
636                                 const char *location)
637 {
638         ev->ops->schedule_immediate(im, ev, handler, private_data,
639                                     handler_name, location);
640 }
641
642 /*
643   add a signal event
644
645   sa_flags are flags to sigaction(2)
646
647   return NULL on failure
648 */
649 struct tevent_signal *_tevent_add_signal(struct tevent_context *ev,
650                                          TALLOC_CTX *mem_ctx,
651                                          int signum,
652                                          int sa_flags,
653                                          tevent_signal_handler_t handler,
654                                          void *private_data,
655                                          const char *handler_name,
656                                          const char *location)
657 {
658         return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data,
659                                    handler_name, location);
660 }
661
662 void tevent_loop_allow_nesting(struct tevent_context *ev)
663 {
664         ev->nesting.allowed = true;
665 }
666
667 void tevent_loop_set_nesting_hook(struct tevent_context *ev,
668                                   tevent_nesting_hook hook,
669                                   void *private_data)
670 {
671         if (ev->nesting.hook_fn && 
672             (ev->nesting.hook_fn != hook ||
673              ev->nesting.hook_private != private_data)) {
674                 /* the way the nesting hook code is currently written
675                    we cannot support two different nesting hooks at the
676                    same time. */
677                 tevent_abort(ev, "tevent: Violation of nesting hook rules\n");
678         }
679         ev->nesting.hook_fn = hook;
680         ev->nesting.hook_private = private_data;
681 }
682
683 static void tevent_abort_nesting(struct tevent_context *ev, const char *location)
684 {
685         const char *reason;
686
687         reason = talloc_asprintf(NULL, "tevent_loop_once() nesting at %s",
688                                  location);
689         if (!reason) {
690                 reason = "tevent_loop_once() nesting";
691         }
692
693         tevent_abort(ev, reason);
694 }
695
696 /*
697   do a single event loop using the events defined in ev 
698 */
699 int _tevent_loop_once(struct tevent_context *ev, const char *location)
700 {
701         int ret;
702         void *nesting_stack_ptr = NULL;
703
704         ev->nesting.level++;
705
706         if (ev->nesting.level > 1) {
707                 if (!ev->nesting.allowed) {
708                         tevent_abort_nesting(ev, location);
709                         errno = ELOOP;
710                         return -1;
711                 }
712         }
713         if (ev->nesting.level > 0) {
714                 if (ev->nesting.hook_fn) {
715                         int ret2;
716                         ret2 = ev->nesting.hook_fn(ev,
717                                                    ev->nesting.hook_private,
718                                                    ev->nesting.level,
719                                                    true,
720                                                    (void *)&nesting_stack_ptr,
721                                                    location);
722                         if (ret2 != 0) {
723                                 ret = ret2;
724                                 goto done;
725                         }
726                 }
727         }
728
729         tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_LOOP_ONCE);
730         ret = ev->ops->loop_once(ev, location);
731         tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_LOOP_ONCE);
732
733         if (ev->nesting.level > 0) {
734                 if (ev->nesting.hook_fn) {
735                         int ret2;
736                         ret2 = ev->nesting.hook_fn(ev,
737                                                    ev->nesting.hook_private,
738                                                    ev->nesting.level,
739                                                    false,
740                                                    (void *)&nesting_stack_ptr,
741                                                    location);
742                         if (ret2 != 0) {
743                                 ret = ret2;
744                                 goto done;
745                         }
746                 }
747         }
748
749 done:
750         ev->nesting.level--;
751         return ret;
752 }
753
754 /*
755   this is a performance optimization for the samba4 nested event loop problems
756 */
757 int _tevent_loop_until(struct tevent_context *ev,
758                        bool (*finished)(void *private_data),
759                        void *private_data,
760                        const char *location)
761 {
762         int ret = 0;
763         void *nesting_stack_ptr = NULL;
764
765         ev->nesting.level++;
766
767         if (ev->nesting.level > 1) {
768                 if (!ev->nesting.allowed) {
769                         tevent_abort_nesting(ev, location);
770                         errno = ELOOP;
771                         return -1;
772                 }
773         }
774         if (ev->nesting.level > 0) {
775                 if (ev->nesting.hook_fn) {
776                         int ret2;
777                         ret2 = ev->nesting.hook_fn(ev,
778                                                    ev->nesting.hook_private,
779                                                    ev->nesting.level,
780                                                    true,
781                                                    (void *)&nesting_stack_ptr,
782                                                    location);
783                         if (ret2 != 0) {
784                                 ret = ret2;
785                                 goto done;
786                         }
787                 }
788         }
789
790         while (!finished(private_data)) {
791                 tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_LOOP_ONCE);
792                 ret = ev->ops->loop_once(ev, location);
793                 tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_LOOP_ONCE);
794                 if (ret != 0) {
795                         break;
796                 }
797         }
798
799         if (ev->nesting.level > 0) {
800                 if (ev->nesting.hook_fn) {
801                         int ret2;
802                         ret2 = ev->nesting.hook_fn(ev,
803                                                    ev->nesting.hook_private,
804                                                    ev->nesting.level,
805                                                    false,
806                                                    (void *)&nesting_stack_ptr,
807                                                    location);
808                         if (ret2 != 0) {
809                                 ret = ret2;
810                                 goto done;
811                         }
812                 }
813         }
814
815 done:
816         ev->nesting.level--;
817         return ret;
818 }
819
820 bool tevent_common_have_events(struct tevent_context *ev)
821 {
822         if (ev->fd_events != NULL) {
823                 if (ev->fd_events != ev->wakeup_fde) {
824                         return true;
825                 }
826                 if (ev->fd_events->next != NULL) {
827                         return true;
828                 }
829
830                 /*
831                  * At this point we just have the wakeup pipe event as
832                  * the only fd_event. That one does not count as a
833                  * regular event, so look at the other event types.
834                  */
835         }
836
837         return ((ev->timer_events != NULL) ||
838                 (ev->immediate_events != NULL) ||
839                 (ev->signal_events != NULL));
840 }
841
842 /*
843   return on failure or (with 0) if all fd events are removed
844 */
845 int tevent_common_loop_wait(struct tevent_context *ev,
846                             const char *location)
847 {
848         /*
849          * loop as long as we have events pending
850          */
851         while (tevent_common_have_events(ev)) {
852                 int ret;
853                 ret = _tevent_loop_once(ev, location);
854                 if (ret != 0) {
855                         tevent_debug(ev, TEVENT_DEBUG_FATAL,
856                                      "_tevent_loop_once() failed: %d - %s\n",
857                                      ret, strerror(errno));
858                         return ret;
859                 }
860         }
861
862         tevent_debug(ev, TEVENT_DEBUG_WARNING,
863                      "tevent_common_loop_wait() out of events\n");
864         return 0;
865 }
866
867 /*
868   return on failure or (with 0) if all fd events are removed
869 */
870 int _tevent_loop_wait(struct tevent_context *ev, const char *location)
871 {
872         return ev->ops->loop_wait(ev, location);
873 }
874
875
876 /*
877   re-initialise a tevent context. This leaves you with the same
878   event context, but all events are wiped and the structure is
879   re-initialised. This is most useful after a fork()  
880
881   zero is returned on success, non-zero on failure
882 */
883 int tevent_re_initialise(struct tevent_context *ev)
884 {
885         tevent_common_context_destructor(ev);
886
887         return ev->ops->context_init(ev);
888 }
889
890 static void wakeup_pipe_handler(struct tevent_context *ev,
891                                 struct tevent_fd *fde,
892                                 uint16_t flags, void *_private)
893 {
894         ssize_t ret;
895
896         do {
897                 /*
898                  * This is the boilerplate for eventfd, but it works
899                  * for pipes too. And as we don't care about the data
900                  * we read, we're fine.
901                  */
902                 uint64_t val;
903                 ret = read(fde->fd, &val, sizeof(val));
904         } while (ret == -1 && errno == EINTR);
905 }
906
907 /*
908  * Initialize the wakeup pipe and pipe fde
909  */
910
911 int tevent_common_wakeup_init(struct tevent_context *ev)
912 {
913         int ret, read_fd;
914
915         if (ev->wakeup_fde != NULL) {
916                 return 0;
917         }
918
919 #ifdef HAVE_EVENTFD
920         ret = eventfd(0, EFD_NONBLOCK);
921         if (ret == -1) {
922                 return errno;
923         }
924         read_fd = ev->wakeup_fd = ret;
925 #else
926         {
927                 int pipe_fds[2];
928                 ret = pipe(pipe_fds);
929                 if (ret == -1) {
930                         return errno;
931                 }
932                 ev->wakeup_fd = pipe_fds[1];
933                 ev->wakeup_read_fd = pipe_fds[0];
934
935                 ev_set_blocking(ev->wakeup_fd, false);
936                 ev_set_blocking(ev->wakeup_read_fd, false);
937
938                 read_fd = ev->wakeup_read_fd;
939         }
940 #endif
941
942         ev->wakeup_fde = tevent_add_fd(ev, ev, read_fd, TEVENT_FD_READ,
943                                      wakeup_pipe_handler, NULL);
944         if (ev->wakeup_fde == NULL) {
945                 close(ev->wakeup_fd);
946 #ifndef HAVE_EVENTFD
947                 close(ev->wakeup_read_fd);
948 #endif
949                 return ENOMEM;
950         }
951
952         return 0;
953 }
954
955 int tevent_common_wakeup_fd(int fd)
956 {
957         ssize_t ret;
958
959         do {
960 #ifdef HAVE_EVENTFD
961                 uint64_t val = 1;
962                 ret = write(fd, &val, sizeof(val));
963 #else
964                 char c = '\0';
965                 ret = write(fd, &c, 1);
966 #endif
967         } while ((ret == -1) && (errno == EINTR));
968
969         return 0;
970 }
971
972 int tevent_common_wakeup(struct tevent_context *ev)
973 {
974         if (ev->wakeup_fde == NULL) {
975                 return ENOTCONN;
976         }
977
978         return tevent_common_wakeup_fd(ev->wakeup_fd);
979 }
980
981 static void tevent_common_wakeup_fini(struct tevent_context *ev)
982 {
983         if (ev->wakeup_fde == NULL) {
984                 return;
985         }
986
987         TALLOC_FREE(ev->wakeup_fde);
988
989         close(ev->wakeup_fd);
990 #ifndef HAVE_EVENTFD
991         close(ev->wakeup_read_fd);
992 #endif
993 }