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