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
67struct 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 */
74static struct tevent_ops_list *tevent_backends = NULL;
75static char *tevent_default_backend = NULL;
76
77/*
78  register an events backend
79*/
80bool 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 */
104void 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*/
114static 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*/
126const 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
142int 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*/
202static 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*/
229struct 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*/
257struct 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  if flags contains TEVENT_FD_AUTOCLOSE then the fd will be closed when
267  the returned fd_event context is freed
268*/
269struct tevent_fd *_tevent_add_fd(struct tevent_context *ev,
270				 TALLOC_CTX *mem_ctx,
271				 int fd,
272				 uint16_t flags,
273				 tevent_fd_handler_t handler,
274				 void *private_data,
275				 const char *handler_name,
276				 const char *location)
277{
278	return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data,
279			       handler_name, location);
280}
281
282/*
283  set a close function on the fd event
284*/
285void tevent_fd_set_close_fn(struct tevent_fd *fde,
286			    tevent_fd_close_fn_t close_fn)
287{
288	if (!fde) return;
289	if (!fde->event_ctx) return;
290	fde->event_ctx->ops->set_fd_close_fn(fde, close_fn);
291}
292
293static void tevent_fd_auto_close_fn(struct tevent_context *ev,
294				    struct tevent_fd *fde,
295				    int fd,
296				    void *private_data)
297{
298	close(fd);
299}
300
301void tevent_fd_set_auto_close(struct tevent_fd *fde)
302{
303	tevent_fd_set_close_fn(fde, tevent_fd_auto_close_fn);
304}
305
306/*
307  return the fd event flags
308*/
309uint16_t tevent_fd_get_flags(struct tevent_fd *fde)
310{
311	if (!fde) return 0;
312	if (!fde->event_ctx) return 0;
313	return fde->event_ctx->ops->get_fd_flags(fde);
314}
315
316/*
317  set the fd event flags
318*/
319void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags)
320{
321	if (!fde) return;
322	if (!fde->event_ctx) return;
323	fde->event_ctx->ops->set_fd_flags(fde, flags);
324}
325
326bool tevent_signal_support(struct tevent_context *ev)
327{
328	if (ev->ops->add_signal) {
329		return true;
330	}
331	return false;
332}
333
334static void (*tevent_abort_fn)(const char *reason);
335
336void tevent_set_abort_fn(void (*abort_fn)(const char *reason))
337{
338	tevent_abort_fn = abort_fn;
339}
340
341static void tevent_abort(struct tevent_context *ev, const char *reason)
342{
343	tevent_debug(ev, TEVENT_DEBUG_FATAL,
344		     "abort: %s\n", reason);
345
346	if (!tevent_abort_fn) {
347		abort();
348	}
349
350	tevent_abort_fn(reason);
351}
352
353/*
354  add a timer event
355  return NULL on failure
356*/
357struct tevent_timer *_tevent_add_timer(struct tevent_context *ev,
358				       TALLOC_CTX *mem_ctx,
359				       struct timeval next_event,
360				       tevent_timer_handler_t handler,
361				       void *private_data,
362				       const char *handler_name,
363				       const char *location)
364{
365	return ev->ops->add_timer(ev, mem_ctx, next_event, handler, private_data,
366				  handler_name, location);
367}
368
369/*
370  allocate an immediate event
371  return NULL on failure (memory allocation error)
372*/
373struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx,
374						  const char *location)
375{
376	struct tevent_immediate *im;
377
378	im = talloc(mem_ctx, struct tevent_immediate);
379	if (im == NULL) return NULL;
380
381	im->prev		= NULL;
382	im->next		= NULL;
383	im->event_ctx		= NULL;
384	im->create_location	= location;
385	im->handler		= NULL;
386	im->private_data	= NULL;
387	im->handler_name	= NULL;
388	im->schedule_location	= NULL;
389	im->cancel_fn		= NULL;
390	im->additional_data	= NULL;
391
392	return im;
393}
394
395/*
396  schedule an immediate event
397  return NULL on failure
398*/
399void _tevent_schedule_immediate(struct tevent_immediate *im,
400				struct tevent_context *ev,
401				tevent_immediate_handler_t handler,
402				void *private_data,
403				const char *handler_name,
404				const char *location)
405{
406	ev->ops->schedule_immediate(im, ev, handler, private_data,
407				    handler_name, location);
408}
409
410/*
411  add a signal event
412
413  sa_flags are flags to sigaction(2)
414
415  return NULL on failure
416*/
417struct tevent_signal *_tevent_add_signal(struct tevent_context *ev,
418					 TALLOC_CTX *mem_ctx,
419					 int signum,
420					 int sa_flags,
421					 tevent_signal_handler_t handler,
422					 void *private_data,
423					 const char *handler_name,
424					 const char *location)
425{
426	return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data,
427				   handler_name, location);
428}
429
430void tevent_loop_allow_nesting(struct tevent_context *ev)
431{
432	ev->nesting.allowed = true;
433}
434
435void tevent_loop_set_nesting_hook(struct tevent_context *ev,
436				  tevent_nesting_hook hook,
437				  void *private_data)
438{
439	if (ev->nesting.hook_fn &&
440	    (ev->nesting.hook_fn != hook ||
441	     ev->nesting.hook_private != private_data)) {
442		/* the way the nesting hook code is currently written
443		   we cannot support two different nesting hooks at the
444		   same time. */
445		tevent_abort(ev, "tevent: Violation of nesting hook rules\n");
446	}
447	ev->nesting.hook_fn = hook;
448	ev->nesting.hook_private = private_data;
449}
450
451static void tevent_abort_nesting(struct tevent_context *ev, const char *location)
452{
453	const char *reason;
454
455	reason = talloc_asprintf(NULL, "tevent_loop_once() nesting at %s",
456				 location);
457	if (!reason) {
458		reason = "tevent_loop_once() nesting";
459	}
460
461	tevent_abort(ev, reason);
462}
463
464/*
465  do a single event loop using the events defined in ev
466*/
467int _tevent_loop_once(struct tevent_context *ev, const char *location)
468{
469	int ret;
470	void *nesting_stack_ptr = NULL;
471
472	ev->nesting.level++;
473
474	if (ev->nesting.level > 1) {
475		if (!ev->nesting.allowed) {
476			tevent_abort_nesting(ev, location);
477			errno = ELOOP;
478			return -1;
479		}
480	}
481	if (ev->nesting.level > 0) {
482		if (ev->nesting.hook_fn) {
483			int ret2;
484			ret2 = ev->nesting.hook_fn(ev,
485						   ev->nesting.hook_private,
486						   ev->nesting.level,
487						   true,
488						   (void *)&nesting_stack_ptr,
489						   location);
490			if (ret2 != 0) {
491				ret = ret2;
492				goto done;
493			}
494		}
495	}
496
497	ret = ev->ops->loop_once(ev, location);
498
499	if (ev->nesting.level > 0) {
500		if (ev->nesting.hook_fn) {
501			int ret2;
502			ret2 = ev->nesting.hook_fn(ev,
503						   ev->nesting.hook_private,
504						   ev->nesting.level,
505						   false,
506						   (void *)&nesting_stack_ptr,
507						   location);
508			if (ret2 != 0) {
509				ret = ret2;
510				goto done;
511			}
512		}
513	}
514
515done:
516	ev->nesting.level--;
517	return ret;
518}
519
520/*
521  this is a performance optimization for the samba4 nested event loop problems
522*/
523int _tevent_loop_until(struct tevent_context *ev,
524		       bool (*finished)(void *private_data),
525		       void *private_data,
526		       const char *location)
527{
528	int ret = 0;
529	void *nesting_stack_ptr = NULL;
530
531	ev->nesting.level++;
532
533	if (ev->nesting.level > 1) {
534		if (!ev->nesting.allowed) {
535			tevent_abort_nesting(ev, location);
536			errno = ELOOP;
537			return -1;
538		}
539	}
540	if (ev->nesting.level > 0) {
541		if (ev->nesting.hook_fn) {
542			int ret2;
543			ret2 = ev->nesting.hook_fn(ev,
544						   ev->nesting.hook_private,
545						   ev->nesting.level,
546						   true,
547						   (void *)&nesting_stack_ptr,
548						   location);
549			if (ret2 != 0) {
550				ret = ret2;
551				goto done;
552			}
553		}
554	}
555
556	while (!finished(private_data)) {
557		ret = ev->ops->loop_once(ev, location);
558		if (ret != 0) {
559			break;
560		}
561	}
562
563	if (ev->nesting.level > 0) {
564		if (ev->nesting.hook_fn) {
565			int ret2;
566			ret2 = ev->nesting.hook_fn(ev,
567						   ev->nesting.hook_private,
568						   ev->nesting.level,
569						   false,
570						   (void *)&nesting_stack_ptr,
571						   location);
572			if (ret2 != 0) {
573				ret = ret2;
574				goto done;
575			}
576		}
577	}
578
579done:
580	ev->nesting.level--;
581	return ret;
582}
583
584/*
585  return on failure or (with 0) if all fd events are removed
586*/
587int tevent_common_loop_wait(struct tevent_context *ev,
588			    const char *location)
589{
590	/*
591	 * loop as long as we have events pending
592	 */
593	while (ev->fd_events ||
594	       ev->timer_events ||
595	       ev->immediate_events ||
596	       ev->signal_events) {
597		int ret;
598		ret = _tevent_loop_once(ev, location);
599		if (ret != 0) {
600			tevent_debug(ev, TEVENT_DEBUG_FATAL,
601				     "_tevent_loop_once() failed: %d - %s\n",
602				     ret, strerror(errno));
603			return ret;
604		}
605	}
606
607	tevent_debug(ev, TEVENT_DEBUG_WARNING,
608		     "tevent_common_loop_wait() out of events\n");
609	return 0;
610}
611
612/*
613  return on failure or (with 0) if all fd events are removed
614*/
615int _tevent_loop_wait(struct tevent_context *ev, const char *location)
616{
617	return ev->ops->loop_wait(ev, location);
618}
619