aa758de64037b35b2cd039119feaf869b08c63e5
[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 #define TEVENT_DEPRECATED 1
63 #include "tevent.h"
64 #include "tevent_internal.h"
65 #include "tevent_util.h"
66
67 struct tevent_ops_list {
68         struct tevent_ops_list *next, *prev;
69         const char *name;
70         const struct tevent_ops *ops;
71 };
72
73 /* list of registered event backends */
74 static struct tevent_ops_list *tevent_backends = NULL;
75 static char *tevent_default_backend = NULL;
76
77 /*
78   register an events backend
79 */
80 bool tevent_register_backend(const char *name, const struct tevent_ops *ops)
81 {
82         struct tevent_ops_list *e;
83
84         for (e = tevent_backends; e != NULL; e = e->next) {
85                 if (0 == strcmp(e->name, name)) {
86                         /* already registered, skip it */
87                         return true;
88                 }
89         }
90
91         e = talloc(NULL, struct tevent_ops_list);
92         if (e == NULL) return false;
93
94         e->name = name;
95         e->ops = ops;
96         DLIST_ADD(tevent_backends, e);
97
98         return true;
99 }
100
101 /*
102   set the default event backend
103  */
104 void tevent_set_default_backend(const char *backend)
105 {
106         talloc_free(tevent_default_backend);
107         tevent_default_backend = talloc_strdup(NULL, backend);
108 }
109
110 /*
111   initialise backends if not already done
112 */
113 static void tevent_backend_init(void)
114 {
115         static bool done;
116
117         if (done) {
118                 return;
119         }
120
121         done = true;
122
123         tevent_select_init();
124         tevent_poll_init();
125         tevent_poll_mt_init();
126 #ifdef HAVE_EPOLL
127         tevent_epoll_init();
128 #endif
129         tevent_standard_init();
130 }
131
132 _PRIVATE_ const struct tevent_ops *tevent_find_ops_byname(const char *name)
133 {
134         struct tevent_ops_list *e;
135
136         tevent_backend_init();
137
138         if (name == NULL) {
139                 name = tevent_default_backend;
140         }
141         if (name == NULL) {
142                 name = "standard";
143         }
144
145         for (e = tevent_backends; e != NULL; e = e->next) {
146                 if (0 == strcmp(e->name, name)) {
147                         return e->ops;
148                 }
149         }
150
151         return NULL;
152 }
153
154 /*
155   list available backends
156 */
157 const char **tevent_backend_list(TALLOC_CTX *mem_ctx)
158 {
159         const char **list = NULL;
160         struct tevent_ops_list *e;
161
162         tevent_backend_init();
163
164         for (e=tevent_backends;e;e=e->next) {
165                 list = ev_str_list_add(list, e->name);
166         }
167
168         talloc_steal(mem_ctx, list);
169
170         return list;
171 }
172
173 int tevent_common_context_destructor(struct tevent_context *ev)
174 {
175         struct tevent_fd *fd, *fn;
176         struct tevent_timer *te, *tn;
177         struct tevent_immediate *ie, *in;
178         struct tevent_signal *se, *sn;
179
180         if (ev->pipe_fde) {
181                 talloc_free(ev->pipe_fde);
182                 close(ev->pipe_fds[0]);
183                 close(ev->pipe_fds[1]);
184                 ev->pipe_fde = NULL;
185         }
186
187         for (fd = ev->fd_events; fd; fd = fn) {
188                 fn = fd->next;
189                 fd->event_ctx = NULL;
190                 DLIST_REMOVE(ev->fd_events, fd);
191         }
192
193         for (te = ev->timer_events; te; te = tn) {
194                 tn = te->next;
195                 te->event_ctx = NULL;
196                 DLIST_REMOVE(ev->timer_events, te);
197         }
198
199         for (ie = ev->immediate_events; ie; ie = in) {
200                 in = ie->next;
201                 ie->event_ctx = NULL;
202                 ie->cancel_fn = NULL;
203                 DLIST_REMOVE(ev->immediate_events, ie);
204         }
205
206         for (se = ev->signal_events; se; se = sn) {
207                 sn = se->next;
208                 se->event_ctx = NULL;
209                 DLIST_REMOVE(ev->signal_events, se);
210                 /*
211                  * This is important, Otherwise signals
212                  * are handled twice in child. eg, SIGHUP.
213                  * one added in parent, and another one in
214                  * the child. -- BoYang
215                  */
216                 tevent_cleanup_pending_signal_handlers(se);
217         }
218
219         /* removing nesting hook or we get an abort when nesting is
220          * not allowed. -- SSS
221          * Note that we need to leave the allowed flag at its current
222          * value, otherwise the use in tevent_re_initialise() will
223          * leave the event context with allowed forced to false, which
224          * will break users that expect nesting to be allowed
225          */
226         ev->nesting.level = 0;
227         ev->nesting.hook_fn = NULL;
228         ev->nesting.hook_private = NULL;
229
230         return 0;
231 }
232
233 /*
234   create a event_context structure for a specific implemementation.
235   This must be the first events call, and all subsequent calls pass
236   this event_context as the first element. Event handlers also
237   receive this as their first argument.
238
239   This function is for allowing third-party-applications to hook in gluecode
240   to their own event loop code, so that they can make async usage of our client libs
241
242   NOTE: use tevent_context_init() inside of samba!
243 */
244 struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx,
245                                                const struct tevent_ops *ops,
246                                                void *additional_data)
247 {
248         struct tevent_context *ev;
249         int ret;
250
251         ev = talloc_zero(mem_ctx, struct tevent_context);
252         if (!ev) return NULL;
253
254         talloc_set_destructor(ev, tevent_common_context_destructor);
255
256         ev->ops = ops;
257         ev->additional_data = additional_data;
258
259         ret = ev->ops->context_init(ev);
260         if (ret != 0) {
261                 talloc_free(ev);
262                 return NULL;
263         }
264
265         return ev;
266 }
267
268 /*
269   create a event_context structure. This must be the first events
270   call, and all subsequent calls pass this event_context as the first
271   element. Event handlers also receive this as their first argument.
272 */
273 struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx,
274                                                   const char *name)
275 {
276         struct tevent_ops *ops;
277
278         ops = tevent_find_ops_byname(name);
279         if (ops == NULL) {
280                 return NULL;
281         }
282
283         return tevent_context_init_ops(mem_ctx, ops, NULL);
284 }
285
286
287 /*
288   create a event_context structure. This must be the first events
289   call, and all subsequent calls pass this event_context as the first
290   element. Event handlers also receive this as their first argument.
291 */
292 struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx)
293 {
294         return tevent_context_init_byname(mem_ctx, NULL);
295 }
296
297 /*
298   add a fd based event
299   return NULL on failure (memory allocation error)
300 */
301 struct tevent_fd *_tevent_add_fd(struct tevent_context *ev,
302                                  TALLOC_CTX *mem_ctx,
303                                  int fd,
304                                  uint16_t flags,
305                                  tevent_fd_handler_t handler,
306                                  void *private_data,
307                                  const char *handler_name,
308                                  const char *location)
309 {
310         return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data,
311                                handler_name, location);
312 }
313
314 /*
315   set a close function on the fd event
316 */
317 void tevent_fd_set_close_fn(struct tevent_fd *fde,
318                             tevent_fd_close_fn_t close_fn)
319 {
320         if (!fde) return;
321         if (!fde->event_ctx) return;
322         fde->event_ctx->ops->set_fd_close_fn(fde, close_fn);
323 }
324
325 static void tevent_fd_auto_close_fn(struct tevent_context *ev,
326                                     struct tevent_fd *fde,
327                                     int fd,
328                                     void *private_data)
329 {
330         close(fd);
331 }
332
333 void tevent_fd_set_auto_close(struct tevent_fd *fde)
334 {
335         tevent_fd_set_close_fn(fde, tevent_fd_auto_close_fn);
336 }
337
338 /*
339   return the fd event flags
340 */
341 uint16_t tevent_fd_get_flags(struct tevent_fd *fde)
342 {
343         if (!fde) return 0;
344         if (!fde->event_ctx) return 0;
345         return fde->event_ctx->ops->get_fd_flags(fde);
346 }
347
348 /*
349   set the fd event flags
350 */
351 void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags)
352 {
353         if (!fde) return;
354         if (!fde->event_ctx) return;
355         fde->event_ctx->ops->set_fd_flags(fde, flags);
356 }
357
358 bool tevent_signal_support(struct tevent_context *ev)
359 {
360         if (ev->ops->add_signal) {
361                 return true;
362         }
363         return false;
364 }
365
366 static void (*tevent_abort_fn)(const char *reason);
367
368 void tevent_set_abort_fn(void (*abort_fn)(const char *reason))
369 {
370         tevent_abort_fn = abort_fn;
371 }
372
373 static void tevent_abort(struct tevent_context *ev, const char *reason)
374 {
375         tevent_debug(ev, TEVENT_DEBUG_FATAL,
376                      "abort: %s\n", reason);
377
378         if (!tevent_abort_fn) {
379                 abort();
380         }
381
382         tevent_abort_fn(reason);
383 }
384
385 /*
386   add a timer event
387   return NULL on failure
388 */
389 struct tevent_timer *_tevent_add_timer(struct tevent_context *ev,
390                                        TALLOC_CTX *mem_ctx,
391                                        struct timeval next_event,
392                                        tevent_timer_handler_t handler,
393                                        void *private_data,
394                                        const char *handler_name,
395                                        const char *location)
396 {
397         return ev->ops->add_timer(ev, mem_ctx, next_event, handler, private_data,
398                                   handler_name, location);
399 }
400
401 /*
402   allocate an immediate event
403   return NULL on failure (memory allocation error)
404 */
405 struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx,
406                                                   const char *location)
407 {
408         struct tevent_immediate *im;
409
410         im = talloc(mem_ctx, struct tevent_immediate);
411         if (im == NULL) return NULL;
412
413         im->prev                = NULL;
414         im->next                = NULL;
415         im->event_ctx           = NULL;
416         im->create_location     = location;
417         im->handler             = NULL;
418         im->private_data        = NULL;
419         im->handler_name        = NULL;
420         im->schedule_location   = NULL;
421         im->cancel_fn           = NULL;
422         im->additional_data     = NULL;
423
424         return im;
425 }
426
427 /*
428   schedule an immediate event
429 */
430 void _tevent_schedule_immediate(struct tevent_immediate *im,
431                                 struct tevent_context *ev,
432                                 tevent_immediate_handler_t handler,
433                                 void *private_data,
434                                 const char *handler_name,
435                                 const char *location)
436 {
437         ev->ops->schedule_immediate(im, ev, handler, private_data,
438                                     handler_name, location);
439 }
440
441 /*
442   add a signal event
443
444   sa_flags are flags to sigaction(2)
445
446   return NULL on failure
447 */
448 struct tevent_signal *_tevent_add_signal(struct tevent_context *ev,
449                                          TALLOC_CTX *mem_ctx,
450                                          int signum,
451                                          int sa_flags,
452                                          tevent_signal_handler_t handler,
453                                          void *private_data,
454                                          const char *handler_name,
455                                          const char *location)
456 {
457         return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data,
458                                    handler_name, location);
459 }
460
461 void tevent_loop_allow_nesting(struct tevent_context *ev)
462 {
463         ev->nesting.allowed = true;
464 }
465
466 void tevent_loop_set_nesting_hook(struct tevent_context *ev,
467                                   tevent_nesting_hook hook,
468                                   void *private_data)
469 {
470         if (ev->nesting.hook_fn && 
471             (ev->nesting.hook_fn != hook ||
472              ev->nesting.hook_private != private_data)) {
473                 /* the way the nesting hook code is currently written
474                    we cannot support two different nesting hooks at the
475                    same time. */
476                 tevent_abort(ev, "tevent: Violation of nesting hook rules\n");
477         }
478         ev->nesting.hook_fn = hook;
479         ev->nesting.hook_private = private_data;
480 }
481
482 static void tevent_abort_nesting(struct tevent_context *ev, const char *location)
483 {
484         const char *reason;
485
486         reason = talloc_asprintf(NULL, "tevent_loop_once() nesting at %s",
487                                  location);
488         if (!reason) {
489                 reason = "tevent_loop_once() nesting";
490         }
491
492         tevent_abort(ev, reason);
493 }
494
495 /*
496   do a single event loop using the events defined in ev 
497 */
498 int _tevent_loop_once(struct tevent_context *ev, const char *location)
499 {
500         int ret;
501         void *nesting_stack_ptr = NULL;
502
503         ev->nesting.level++;
504
505         if (ev->nesting.level > 1) {
506                 if (!ev->nesting.allowed) {
507                         tevent_abort_nesting(ev, location);
508                         errno = ELOOP;
509                         return -1;
510                 }
511         }
512         if (ev->nesting.level > 0) {
513                 if (ev->nesting.hook_fn) {
514                         int ret2;
515                         ret2 = ev->nesting.hook_fn(ev,
516                                                    ev->nesting.hook_private,
517                                                    ev->nesting.level,
518                                                    true,
519                                                    (void *)&nesting_stack_ptr,
520                                                    location);
521                         if (ret2 != 0) {
522                                 ret = ret2;
523                                 goto done;
524                         }
525                 }
526         }
527
528         ret = ev->ops->loop_once(ev, location);
529
530         if (ev->nesting.level > 0) {
531                 if (ev->nesting.hook_fn) {
532                         int ret2;
533                         ret2 = ev->nesting.hook_fn(ev,
534                                                    ev->nesting.hook_private,
535                                                    ev->nesting.level,
536                                                    false,
537                                                    (void *)&nesting_stack_ptr,
538                                                    location);
539                         if (ret2 != 0) {
540                                 ret = ret2;
541                                 goto done;
542                         }
543                 }
544         }
545
546 done:
547         ev->nesting.level--;
548         return ret;
549 }
550
551 /*
552   this is a performance optimization for the samba4 nested event loop problems
553 */
554 int _tevent_loop_until(struct tevent_context *ev,
555                        bool (*finished)(void *private_data),
556                        void *private_data,
557                        const char *location)
558 {
559         int ret = 0;
560         void *nesting_stack_ptr = NULL;
561
562         ev->nesting.level++;
563
564         if (ev->nesting.level > 1) {
565                 if (!ev->nesting.allowed) {
566                         tevent_abort_nesting(ev, location);
567                         errno = ELOOP;
568                         return -1;
569                 }
570         }
571         if (ev->nesting.level > 0) {
572                 if (ev->nesting.hook_fn) {
573                         int ret2;
574                         ret2 = ev->nesting.hook_fn(ev,
575                                                    ev->nesting.hook_private,
576                                                    ev->nesting.level,
577                                                    true,
578                                                    (void *)&nesting_stack_ptr,
579                                                    location);
580                         if (ret2 != 0) {
581                                 ret = ret2;
582                                 goto done;
583                         }
584                 }
585         }
586
587         while (!finished(private_data)) {
588                 ret = ev->ops->loop_once(ev, location);
589                 if (ret != 0) {
590                         break;
591                 }
592         }
593
594         if (ev->nesting.level > 0) {
595                 if (ev->nesting.hook_fn) {
596                         int ret2;
597                         ret2 = ev->nesting.hook_fn(ev,
598                                                    ev->nesting.hook_private,
599                                                    ev->nesting.level,
600                                                    false,
601                                                    (void *)&nesting_stack_ptr,
602                                                    location);
603                         if (ret2 != 0) {
604                                 ret = ret2;
605                                 goto done;
606                         }
607                 }
608         }
609
610 done:
611         ev->nesting.level--;
612         return ret;
613 }
614
615 /*
616   return on failure or (with 0) if all fd events are removed
617 */
618 int tevent_common_loop_wait(struct tevent_context *ev,
619                             const char *location)
620 {
621         /*
622          * loop as long as we have events pending
623          */
624         while (ev->fd_events ||
625                ev->timer_events ||
626                ev->immediate_events ||
627                ev->signal_events) {
628                 int ret;
629                 ret = _tevent_loop_once(ev, location);
630                 if (ret != 0) {
631                         tevent_debug(ev, TEVENT_DEBUG_FATAL,
632                                      "_tevent_loop_once() failed: %d - %s\n",
633                                      ret, strerror(errno));
634                         return ret;
635                 }
636         }
637
638         tevent_debug(ev, TEVENT_DEBUG_WARNING,
639                      "tevent_common_loop_wait() out of events\n");
640         return 0;
641 }
642
643 /*
644   return on failure or (with 0) if all fd events are removed
645 */
646 int _tevent_loop_wait(struct tevent_context *ev, const char *location)
647 {
648         return ev->ops->loop_wait(ev, location);
649 }
650
651
652 /*
653   re-initialise a tevent context. This leaves you with the same
654   event context, but all events are wiped and the structure is
655   re-initialised. This is most useful after a fork()  
656
657   zero is returned on success, non-zero on failure
658 */
659 int tevent_re_initialise(struct tevent_context *ev)
660 {
661         tevent_common_context_destructor(ev);
662
663         return ev->ops->context_init(ev);
664 }