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