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