summaryrefslogtreecommitdiff
path: root/lib/tevent/tevent.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tevent/tevent.c')
-rw-r--r--lib/tevent/tevent.c93
1 files changed, 91 insertions, 2 deletions
diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c
index 867cfc08fe..0c02e46f3c 100644
--- a/lib/tevent/tevent.c
+++ b/lib/tevent/tevent.c
@@ -143,6 +143,7 @@ int tevent_common_context_destructor(struct tevent_context *ev)
{
struct tevent_fd *fd, *fn;
struct tevent_timer *te, *tn;
+ struct tevent_immediate *ie, *in;
struct tevent_signal *se, *sn;
if (ev->pipe_fde) {
@@ -162,6 +163,13 @@ int tevent_common_context_destructor(struct tevent_context *ev)
DLIST_REMOVE(ev->timer_events, te);
}
+ for (ie = ev->immediate_events; ie; ie = in) {
+ in = ie->next;
+ ie->event_ctx = NULL;
+ ie->cancel_fn = NULL;
+ DLIST_REMOVE(ev->immediate_events, ie);
+ }
+
for (se = ev->signal_events; se; se = sn) {
sn = se->next;
se->event_ctx = NULL;
@@ -350,6 +358,47 @@ struct tevent_timer *_tevent_add_timer(struct tevent_context *ev,
}
/*
+ allocate an immediate event
+ return NULL on failure (memory allocation error)
+*/
+struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx,
+ const char *location)
+{
+ struct tevent_immediate *im;
+
+ im = talloc(mem_ctx, struct tevent_immediate);
+ if (im == NULL) return NULL;
+
+ im->prev = NULL;
+ im->next = NULL;
+ im->event_ctx = NULL;
+ im->create_location = location;
+ im->handler = NULL;
+ im->private_data = NULL;
+ im->handler_name = NULL;
+ im->schedule_location = NULL;
+ im->cancel_fn = NULL;
+ im->additional_data = NULL;
+
+ return im;
+}
+
+/*
+ schedule an immediate event
+ return NULL on failure
+*/
+void _tevent_schedule_immediate(struct tevent_immediate *im,
+ struct tevent_context *ev,
+ tevent_immediate_handler_t handler,
+ void *private_data,
+ const char *handler_name,
+ const char *location)
+{
+ ev->ops->schedule_immediate(im, ev, handler, private_data,
+ handler_name, location);
+}
+
+/*
add a signal event
sa_flags are flags to sigaction(2)
@@ -378,6 +427,14 @@ void tevent_loop_set_nesting_hook(struct tevent_context *ev,
tevent_nesting_hook hook,
void *private_data)
{
+ if (ev->nesting.hook_fn &&
+ (ev->nesting.hook_fn != hook ||
+ ev->nesting.hook_private != private_data)) {
+ /* the way the nesting hook code is currently written
+ we cannot support two different nesting hooks at the
+ same time. */
+ tevent_abort(ev, "tevent: Violation of nesting hook rules\n");
+ }
ev->nesting.hook_fn = hook;
ev->nesting.hook_private = private_data;
}
@@ -411,6 +468,8 @@ int _tevent_loop_once(struct tevent_context *ev, const char *location)
errno = ELOOP;
return -1;
}
+ }
+ if (ev->nesting.level > 0) {
if (ev->nesting.hook_fn) {
int ret2;
ret2 = ev->nesting.hook_fn(ev,
@@ -428,7 +487,7 @@ int _tevent_loop_once(struct tevent_context *ev, const char *location)
ret = ev->ops->loop_once(ev, location);
- if (ev->nesting.level > 1) {
+ if (ev->nesting.level > 0) {
if (ev->nesting.hook_fn) {
int ret2;
ret2 = ev->nesting.hook_fn(ev,
@@ -468,6 +527,8 @@ int _tevent_loop_until(struct tevent_context *ev,
errno = ELOOP;
return -1;
}
+ }
+ if (ev->nesting.level > 0) {
if (ev->nesting.hook_fn) {
int ret2;
ret2 = ev->nesting.hook_fn(ev,
@@ -490,7 +551,7 @@ int _tevent_loop_until(struct tevent_context *ev,
}
}
- if (ev->nesting.level > 1) {
+ if (ev->nesting.level > 0) {
if (ev->nesting.hook_fn) {
int ret2;
ret2 = ev->nesting.hook_fn(ev,
@@ -514,6 +575,34 @@ done:
/*
return on failure or (with 0) if all fd events are removed
*/
+int tevent_common_loop_wait(struct tevent_context *ev,
+ const char *location)
+{
+ /*
+ * loop as long as we have events pending
+ */
+ while (ev->fd_events ||
+ ev->timer_events ||
+ ev->immediate_events ||
+ ev->signal_events) {
+ int ret;
+ ret = _tevent_loop_once(ev, location);
+ if (ret != 0) {
+ tevent_debug(ev, TEVENT_DEBUG_FATAL,
+ "_tevent_loop_once() failed: %d - %s\n",
+ ret, strerror(errno));
+ return ret;
+ }
+ }
+
+ tevent_debug(ev, TEVENT_DEBUG_WARNING,
+ "tevent_common_loop_wait() out of events\n");
+ return 0;
+}
+
+/*
+ return on failure or (with 0) if all fd events are removed
+*/
int _tevent_loop_wait(struct tevent_context *ev, const char *location)
{
return ev->ops->loop_wait(ev, location);