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