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