tevent: don't force the nesting flag to false in the destructor
[nivanova/samba-autobuild/.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   return NULL on failure
406 */
407 void _tevent_schedule_immediate(struct tevent_immediate *im,
408                                 struct tevent_context *ev,
409                                 tevent_immediate_handler_t handler,
410                                 void *private_data,
411                                 const char *handler_name,
412                                 const char *location)
413 {
414         ev->ops->schedule_immediate(im, ev, handler, private_data,
415                                     handler_name, location);
416 }
417
418 /*
419   add a signal event
420
421   sa_flags are flags to sigaction(2)
422
423   return NULL on failure
424 */
425 struct tevent_signal *_tevent_add_signal(struct tevent_context *ev,
426                                          TALLOC_CTX *mem_ctx,
427                                          int signum,
428                                          int sa_flags,
429                                          tevent_signal_handler_t handler,
430                                          void *private_data,
431                                          const char *handler_name,
432                                          const char *location)
433 {
434         return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data,
435                                    handler_name, location);
436 }
437
438 void tevent_loop_allow_nesting(struct tevent_context *ev)
439 {
440         ev->nesting.allowed = true;
441 }
442
443 void tevent_loop_set_nesting_hook(struct tevent_context *ev,
444                                   tevent_nesting_hook hook,
445                                   void *private_data)
446 {
447         if (ev->nesting.hook_fn && 
448             (ev->nesting.hook_fn != hook ||
449              ev->nesting.hook_private != private_data)) {
450                 /* the way the nesting hook code is currently written
451                    we cannot support two different nesting hooks at the
452                    same time. */
453                 tevent_abort(ev, "tevent: Violation of nesting hook rules\n");
454         }
455         ev->nesting.hook_fn = hook;
456         ev->nesting.hook_private = private_data;
457 }
458
459 static void tevent_abort_nesting(struct tevent_context *ev, const char *location)
460 {
461         const char *reason;
462
463         reason = talloc_asprintf(NULL, "tevent_loop_once() nesting at %s",
464                                  location);
465         if (!reason) {
466                 reason = "tevent_loop_once() nesting";
467         }
468
469         tevent_abort(ev, reason);
470 }
471
472 /*
473   do a single event loop using the events defined in ev 
474 */
475 int _tevent_loop_once(struct tevent_context *ev, const char *location)
476 {
477         int ret;
478         void *nesting_stack_ptr = NULL;
479
480         ev->nesting.level++;
481
482         if (ev->nesting.level > 1) {
483                 if (!ev->nesting.allowed) {
484                         tevent_abort_nesting(ev, location);
485                         errno = ELOOP;
486                         return -1;
487                 }
488         }
489         if (ev->nesting.level > 0) {
490                 if (ev->nesting.hook_fn) {
491                         int ret2;
492                         ret2 = ev->nesting.hook_fn(ev,
493                                                    ev->nesting.hook_private,
494                                                    ev->nesting.level,
495                                                    true,
496                                                    (void *)&nesting_stack_ptr,
497                                                    location);
498                         if (ret2 != 0) {
499                                 ret = ret2;
500                                 goto done;
501                         }
502                 }
503         }
504
505         ret = ev->ops->loop_once(ev, location);
506
507         if (ev->nesting.level > 0) {
508                 if (ev->nesting.hook_fn) {
509                         int ret2;
510                         ret2 = ev->nesting.hook_fn(ev,
511                                                    ev->nesting.hook_private,
512                                                    ev->nesting.level,
513                                                    false,
514                                                    (void *)&nesting_stack_ptr,
515                                                    location);
516                         if (ret2 != 0) {
517                                 ret = ret2;
518                                 goto done;
519                         }
520                 }
521         }
522
523 done:
524         ev->nesting.level--;
525         return ret;
526 }
527
528 /*
529   this is a performance optimization for the samba4 nested event loop problems
530 */
531 int _tevent_loop_until(struct tevent_context *ev,
532                        bool (*finished)(void *private_data),
533                        void *private_data,
534                        const char *location)
535 {
536         int ret = 0;
537         void *nesting_stack_ptr = NULL;
538
539         ev->nesting.level++;
540
541         if (ev->nesting.level > 1) {
542                 if (!ev->nesting.allowed) {
543                         tevent_abort_nesting(ev, location);
544                         errno = ELOOP;
545                         return -1;
546                 }
547         }
548         if (ev->nesting.level > 0) {
549                 if (ev->nesting.hook_fn) {
550                         int ret2;
551                         ret2 = ev->nesting.hook_fn(ev,
552                                                    ev->nesting.hook_private,
553                                                    ev->nesting.level,
554                                                    true,
555                                                    (void *)&nesting_stack_ptr,
556                                                    location);
557                         if (ret2 != 0) {
558                                 ret = ret2;
559                                 goto done;
560                         }
561                 }
562         }
563
564         while (!finished(private_data)) {
565                 ret = ev->ops->loop_once(ev, location);
566                 if (ret != 0) {
567                         break;
568                 }
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                                                    false,
578                                                    (void *)&nesting_stack_ptr,
579                                                    location);
580                         if (ret2 != 0) {
581                                 ret = ret2;
582                                 goto done;
583                         }
584                 }
585         }
586
587 done:
588         ev->nesting.level--;
589         return ret;
590 }
591
592 /*
593   return on failure or (with 0) if all fd events are removed
594 */
595 int tevent_common_loop_wait(struct tevent_context *ev,
596                             const char *location)
597 {
598         /*
599          * loop as long as we have events pending
600          */
601         while (ev->fd_events ||
602                ev->timer_events ||
603                ev->immediate_events ||
604                ev->signal_events) {
605                 int ret;
606                 ret = _tevent_loop_once(ev, location);
607                 if (ret != 0) {
608                         tevent_debug(ev, TEVENT_DEBUG_FATAL,
609                                      "_tevent_loop_once() failed: %d - %s\n",
610                                      ret, strerror(errno));
611                         return ret;
612                 }
613         }
614
615         tevent_debug(ev, TEVENT_DEBUG_WARNING,
616                      "tevent_common_loop_wait() out of events\n");
617         return 0;
618 }
619
620 /*
621   return on failure or (with 0) if all fd events are removed
622 */
623 int _tevent_loop_wait(struct tevent_context *ev, const char *location)
624 {
625         return ev->ops->loop_wait(ev, location);
626 }
627
628
629 /*
630   re-initialise a tevent context. This leaves you with the same
631   event context, but all events are wiped and the structure is
632   re-initialised. This is most useful after a fork()  
633
634   zero is returned on success, non-zero on failure
635 */
636 int tevent_re_initialise(struct tevent_context *ev)
637 {
638         tevent_common_context_destructor(ev);
639
640         return ev->ops->context_init(ev);
641 }