Revert "tevent zero..."
[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         ret = ev->ops->context_init(ev);
413         if (ret != 0) {
414                 talloc_free(ev);
415                 return NULL;
416         }
417
418         return ev;
419 }
420
421 /*
422   create a event_context structure. This must be the first events
423   call, and all subsequent calls pass this event_context as the first
424   element. Event handlers also receive this as their first argument.
425 */
426 struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx,
427                                                   const char *name)
428 {
429         const struct tevent_ops *ops;
430
431         ops = tevent_find_ops_byname(name);
432         if (ops == NULL) {
433                 return NULL;
434         }
435
436         return tevent_context_init_ops(mem_ctx, ops, NULL);
437 }
438
439
440 /*
441   create a event_context structure. This must be the first events
442   call, and all subsequent calls pass this event_context as the first
443   element. Event handlers also receive this as their first argument.
444 */
445 struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx)
446 {
447         return tevent_context_init_byname(mem_ctx, NULL);
448 }
449
450 /*
451   add a fd based event
452   return NULL on failure (memory allocation error)
453 */
454 struct tevent_fd *_tevent_add_fd(struct tevent_context *ev,
455                                  TALLOC_CTX *mem_ctx,
456                                  int fd,
457                                  uint16_t flags,
458                                  tevent_fd_handler_t handler,
459                                  void *private_data,
460                                  const char *handler_name,
461                                  const char *location)
462 {
463         return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data,
464                                handler_name, location);
465 }
466
467 /*
468   set a close function on the fd event
469 */
470 void tevent_fd_set_close_fn(struct tevent_fd *fde,
471                             tevent_fd_close_fn_t close_fn)
472 {
473         if (!fde) return;
474         if (!fde->event_ctx) return;
475         fde->event_ctx->ops->set_fd_close_fn(fde, close_fn);
476 }
477
478 static void tevent_fd_auto_close_fn(struct tevent_context *ev,
479                                     struct tevent_fd *fde,
480                                     int fd,
481                                     void *private_data)
482 {
483         close(fd);
484 }
485
486 void tevent_fd_set_auto_close(struct tevent_fd *fde)
487 {
488         tevent_fd_set_close_fn(fde, tevent_fd_auto_close_fn);
489 }
490
491 /*
492   return the fd event flags
493 */
494 uint16_t tevent_fd_get_flags(struct tevent_fd *fde)
495 {
496         if (!fde) return 0;
497         if (!fde->event_ctx) return 0;
498         return fde->event_ctx->ops->get_fd_flags(fde);
499 }
500
501 /*
502   set the fd event flags
503 */
504 void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags)
505 {
506         if (!fde) return;
507         if (!fde->event_ctx) return;
508         fde->event_ctx->ops->set_fd_flags(fde, flags);
509 }
510
511 bool tevent_signal_support(struct tevent_context *ev)
512 {
513         if (ev->ops->add_signal) {
514                 return true;
515         }
516         return false;
517 }
518
519 static void (*tevent_abort_fn)(const char *reason);
520
521 void tevent_set_abort_fn(void (*abort_fn)(const char *reason))
522 {
523         tevent_abort_fn = abort_fn;
524 }
525
526 static void tevent_abort(struct tevent_context *ev, const char *reason)
527 {
528         tevent_debug(ev, TEVENT_DEBUG_FATAL,
529                      "abort: %s\n", reason);
530
531         if (!tevent_abort_fn) {
532                 abort();
533         }
534
535         tevent_abort_fn(reason);
536 }
537
538 /*
539   add a timer event
540   return NULL on failure
541 */
542 struct tevent_timer *_tevent_add_timer(struct tevent_context *ev,
543                                        TALLOC_CTX *mem_ctx,
544                                        struct timeval next_event,
545                                        tevent_timer_handler_t handler,
546                                        void *private_data,
547                                        const char *handler_name,
548                                        const char *location)
549 {
550         return ev->ops->add_timer(ev, mem_ctx, next_event, handler, private_data,
551                                   handler_name, location);
552 }
553
554 /*
555   allocate an immediate event
556   return NULL on failure (memory allocation error)
557 */
558 struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx,
559                                                   const char *location)
560 {
561         struct tevent_immediate *im;
562
563         im = talloc(mem_ctx, struct tevent_immediate);
564         if (im == NULL) return NULL;
565
566         im->prev                = NULL;
567         im->next                = NULL;
568         im->event_ctx           = NULL;
569         im->create_location     = location;
570         im->handler             = NULL;
571         im->private_data        = NULL;
572         im->handler_name        = NULL;
573         im->schedule_location   = NULL;
574         im->cancel_fn           = NULL;
575         im->additional_data     = NULL;
576
577         return im;
578 }
579
580 /*
581   schedule an immediate event
582 */
583 void _tevent_schedule_immediate(struct tevent_immediate *im,
584                                 struct tevent_context *ev,
585                                 tevent_immediate_handler_t handler,
586                                 void *private_data,
587                                 const char *handler_name,
588                                 const char *location)
589 {
590         ev->ops->schedule_immediate(im, ev, handler, private_data,
591                                     handler_name, location);
592 }
593
594 /*
595   add a signal event
596
597   sa_flags are flags to sigaction(2)
598
599   return NULL on failure
600 */
601 struct tevent_signal *_tevent_add_signal(struct tevent_context *ev,
602                                          TALLOC_CTX *mem_ctx,
603                                          int signum,
604                                          int sa_flags,
605                                          tevent_signal_handler_t handler,
606                                          void *private_data,
607                                          const char *handler_name,
608                                          const char *location)
609 {
610         return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data,
611                                    handler_name, location);
612 }
613
614 void tevent_loop_allow_nesting(struct tevent_context *ev)
615 {
616         ev->nesting.allowed = true;
617 }
618
619 void tevent_loop_set_nesting_hook(struct tevent_context *ev,
620                                   tevent_nesting_hook hook,
621                                   void *private_data)
622 {
623         if (ev->nesting.hook_fn && 
624             (ev->nesting.hook_fn != hook ||
625              ev->nesting.hook_private != private_data)) {
626                 /* the way the nesting hook code is currently written
627                    we cannot support two different nesting hooks at the
628                    same time. */
629                 tevent_abort(ev, "tevent: Violation of nesting hook rules\n");
630         }
631         ev->nesting.hook_fn = hook;
632         ev->nesting.hook_private = private_data;
633 }
634
635 static void tevent_abort_nesting(struct tevent_context *ev, const char *location)
636 {
637         const char *reason;
638
639         reason = talloc_asprintf(NULL, "tevent_loop_once() nesting at %s",
640                                  location);
641         if (!reason) {
642                 reason = "tevent_loop_once() nesting";
643         }
644
645         tevent_abort(ev, reason);
646 }
647
648 /*
649   do a single event loop using the events defined in ev 
650 */
651 int _tevent_loop_once(struct tevent_context *ev, const char *location)
652 {
653         int ret;
654         void *nesting_stack_ptr = NULL;
655
656         ev->nesting.level++;
657
658         if (ev->nesting.level > 1) {
659                 if (!ev->nesting.allowed) {
660                         tevent_abort_nesting(ev, location);
661                         errno = ELOOP;
662                         return -1;
663                 }
664         }
665         if (ev->nesting.level > 0) {
666                 if (ev->nesting.hook_fn) {
667                         int ret2;
668                         ret2 = ev->nesting.hook_fn(ev,
669                                                    ev->nesting.hook_private,
670                                                    ev->nesting.level,
671                                                    true,
672                                                    (void *)&nesting_stack_ptr,
673                                                    location);
674                         if (ret2 != 0) {
675                                 ret = ret2;
676                                 goto done;
677                         }
678                 }
679         }
680
681         tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_LOOP_ONCE);
682         ret = ev->ops->loop_once(ev, location);
683         tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_LOOP_ONCE);
684
685         if (ev->nesting.level > 0) {
686                 if (ev->nesting.hook_fn) {
687                         int ret2;
688                         ret2 = ev->nesting.hook_fn(ev,
689                                                    ev->nesting.hook_private,
690                                                    ev->nesting.level,
691                                                    false,
692                                                    (void *)&nesting_stack_ptr,
693                                                    location);
694                         if (ret2 != 0) {
695                                 ret = ret2;
696                                 goto done;
697                         }
698                 }
699         }
700
701 done:
702         ev->nesting.level--;
703         return ret;
704 }
705
706 /*
707   this is a performance optimization for the samba4 nested event loop problems
708 */
709 int _tevent_loop_until(struct tevent_context *ev,
710                        bool (*finished)(void *private_data),
711                        void *private_data,
712                        const char *location)
713 {
714         int ret = 0;
715         void *nesting_stack_ptr = NULL;
716
717         ev->nesting.level++;
718
719         if (ev->nesting.level > 1) {
720                 if (!ev->nesting.allowed) {
721                         tevent_abort_nesting(ev, location);
722                         errno = ELOOP;
723                         return -1;
724                 }
725         }
726         if (ev->nesting.level > 0) {
727                 if (ev->nesting.hook_fn) {
728                         int ret2;
729                         ret2 = ev->nesting.hook_fn(ev,
730                                                    ev->nesting.hook_private,
731                                                    ev->nesting.level,
732                                                    true,
733                                                    (void *)&nesting_stack_ptr,
734                                                    location);
735                         if (ret2 != 0) {
736                                 ret = ret2;
737                                 goto done;
738                         }
739                 }
740         }
741
742         while (!finished(private_data)) {
743                 tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_LOOP_ONCE);
744                 ret = ev->ops->loop_once(ev, location);
745                 tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_LOOP_ONCE);
746                 if (ret != 0) {
747                         break;
748                 }
749         }
750
751         if (ev->nesting.level > 0) {
752                 if (ev->nesting.hook_fn) {
753                         int ret2;
754                         ret2 = ev->nesting.hook_fn(ev,
755                                                    ev->nesting.hook_private,
756                                                    ev->nesting.level,
757                                                    false,
758                                                    (void *)&nesting_stack_ptr,
759                                                    location);
760                         if (ret2 != 0) {
761                                 ret = ret2;
762                                 goto done;
763                         }
764                 }
765         }
766
767 done:
768         ev->nesting.level--;
769         return ret;
770 }
771
772 bool tevent_common_have_events(struct tevent_context *ev)
773 {
774         if (ev->fd_events != NULL) {
775                 if (ev->fd_events != ev->wakeup_fde) {
776                         return true;
777                 }
778                 if (ev->fd_events->next != NULL) {
779                         return true;
780                 }
781
782                 /*
783                  * At this point we just have the wakeup pipe event as
784                  * the only fd_event. That one does not count as a
785                  * regular event, so look at the other event types.
786                  */
787         }
788
789         return ((ev->timer_events != NULL) ||
790                 (ev->immediate_events != NULL) ||
791                 (ev->signal_events != NULL));
792 }
793
794 /*
795   return on failure or (with 0) if all fd events are removed
796 */
797 int tevent_common_loop_wait(struct tevent_context *ev,
798                             const char *location)
799 {
800         /*
801          * loop as long as we have events pending
802          */
803         while (tevent_common_have_events(ev)) {
804                 int ret;
805                 ret = _tevent_loop_once(ev, location);
806                 if (ret != 0) {
807                         tevent_debug(ev, TEVENT_DEBUG_FATAL,
808                                      "_tevent_loop_once() failed: %d - %s\n",
809                                      ret, strerror(errno));
810                         return ret;
811                 }
812         }
813
814         tevent_debug(ev, TEVENT_DEBUG_WARNING,
815                      "tevent_common_loop_wait() out of events\n");
816         return 0;
817 }
818
819 /*
820   return on failure or (with 0) if all fd events are removed
821 */
822 int _tevent_loop_wait(struct tevent_context *ev, const char *location)
823 {
824         return ev->ops->loop_wait(ev, location);
825 }
826
827
828 /*
829   re-initialise a tevent context. This leaves you with the same
830   event context, but all events are wiped and the structure is
831   re-initialised. This is most useful after a fork()  
832
833   zero is returned on success, non-zero on failure
834 */
835 int tevent_re_initialise(struct tevent_context *ev)
836 {
837         tevent_common_context_destructor(ev);
838
839         return ev->ops->context_init(ev);
840 }
841
842 static void wakeup_pipe_handler(struct tevent_context *ev,
843                                 struct tevent_fd *fde,
844                                 uint16_t flags, void *_private)
845 {
846         ssize_t ret;
847
848         do {
849                 /*
850                  * This is the boilerplate for eventfd, but it works
851                  * for pipes too. And as we don't care about the data
852                  * we read, we're fine.
853                  */
854                 uint64_t val;
855                 ret = read(fde->fd, &val, sizeof(val));
856         } while (ret == -1 && errno == EINTR);
857 }
858
859 /*
860  * Initialize the wakeup pipe and pipe fde
861  */
862
863 int tevent_common_wakeup_init(struct tevent_context *ev)
864 {
865         int ret;
866
867         if (ev->wakeup_fde != NULL) {
868                 return 0;
869         }
870
871 #ifdef HAVE_EVENTFD
872         ret = eventfd(0, EFD_NONBLOCK);
873         if (ret == -1) {
874                 return errno;
875         }
876         ev->wakeup_fd = ret;
877 #else
878         {
879                 int pipe_fds[2];
880                 ret = pipe(pipe_fds);
881                 if (ret == -1) {
882                         return errno;
883                 }
884                 ev->wakeup_fd = pipe_fds[0];
885                 ev->wakeup_write_fd = pipe_fds[1];
886
887                 ev_set_blocking(ev->wakeup_fd, false);
888                 ev_set_blocking(ev->wakeup_write_fd, false);
889         }
890 #endif
891
892         ev->wakeup_fde = tevent_add_fd(ev, ev, ev->wakeup_fd,
893                                      TEVENT_FD_READ,
894                                      wakeup_pipe_handler, NULL);
895         if (ev->wakeup_fde == NULL) {
896                 close(ev->wakeup_fd);
897 #ifndef HAVE_EVENTFD
898                 close(ev->wakeup_write_fd);
899 #endif
900                 return ENOMEM;
901         }
902
903         return 0;
904 }
905
906 int tevent_common_wakeup(struct tevent_context *ev)
907 {
908         ssize_t ret;
909
910         if (ev->wakeup_fde == NULL) {
911                 return ENOTCONN;
912         }
913
914         do {
915 #ifdef HAVE_EVENTFD
916                 uint64_t val = 1;
917                 ret = write(ev->wakeup_fd, &val, sizeof(val));
918 #else
919                 char c = '\0';
920                 ret = write(ev->wakeup_write_fd, &c, 1);
921 #endif
922         } while ((ret == -1) && (errno == EINTR));
923
924         return 0;
925 }
926
927 static void tevent_common_wakeup_fini(struct tevent_context *ev)
928 {
929         if (ev->wakeup_fde == NULL) {
930                 return;
931         }
932
933         TALLOC_FREE(ev->wakeup_fde);
934
935         close(ev->wakeup_fd);
936 #ifndef HAVE_EVENTFD
937         close(ev->wakeup_write_fd);
938 #endif
939 }