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