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.c170
1 files changed, 166 insertions, 4 deletions
diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c
index fc8252960a..867cfc08fe 100644
--- a/lib/tevent/tevent.c
+++ b/lib/tevent/tevent.c
@@ -59,6 +59,7 @@
*/
#include "replace.h"
#include "system/filesys.h"
+#define TEVENT_DEPRECATED 1
#include "tevent.h"
#include "tevent_internal.h"
#include "tevent_util.h"
@@ -305,6 +306,33 @@ void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags)
fde->event_ctx->ops->set_fd_flags(fde, flags);
}
+bool tevent_signal_support(struct tevent_context *ev)
+{
+ if (ev->ops->add_signal) {
+ return true;
+ }
+ return false;
+}
+
+static void (*tevent_abort_fn)(const char *reason);
+
+void tevent_set_abort_fn(void (*abort_fn)(const char *reason))
+{
+ tevent_abort_fn = abort_fn;
+}
+
+static void tevent_abort(struct tevent_context *ev, const char *reason)
+{
+ tevent_debug(ev, TEVENT_DEBUG_FATAL,
+ "abort: %s\n", reason);
+
+ if (!tevent_abort_fn) {
+ abort();
+ }
+
+ tevent_abort_fn(reason);
+}
+
/*
add a timer event
return NULL on failure
@@ -341,18 +369,152 @@ struct tevent_signal *_tevent_add_signal(struct tevent_context *ev,
handler_name, location);
}
+void tevent_loop_allow_nesting(struct tevent_context *ev)
+{
+ ev->nesting.allowed = true;
+}
+
+void tevent_loop_set_nesting_hook(struct tevent_context *ev,
+ tevent_nesting_hook hook,
+ void *private_data)
+{
+ ev->nesting.hook_fn = hook;
+ ev->nesting.hook_private = private_data;
+}
+
+static void tevent_abort_nesting(struct tevent_context *ev, const char *location)
+{
+ const char *reason;
+
+ reason = talloc_asprintf(NULL, "tevent_loop_once() nesting at %s",
+ location);
+ if (!reason) {
+ reason = "tevent_loop_once() nesting";
+ }
+
+ tevent_abort(ev, reason);
+}
+
/*
do a single event loop using the events defined in ev
*/
-int tevent_loop_once(struct tevent_context *ev)
+int _tevent_loop_once(struct tevent_context *ev, const char *location)
{
- return ev->ops->loop_once(ev);
+ int ret;
+ void *nesting_stack_ptr = NULL;
+
+ ev->nesting.level++;
+
+ if (ev->nesting.level > 1) {
+ if (!ev->nesting.allowed) {
+ tevent_abort_nesting(ev, location);
+ errno = ELOOP;
+ return -1;
+ }
+ if (ev->nesting.hook_fn) {
+ int ret2;
+ ret2 = ev->nesting.hook_fn(ev,
+ ev->nesting.hook_private,
+ ev->nesting.level,
+ true,
+ (void *)&nesting_stack_ptr,
+ location);
+ if (ret2 != 0) {
+ ret = ret2;
+ goto done;
+ }
+ }
+ }
+
+ ret = ev->ops->loop_once(ev, location);
+
+ if (ev->nesting.level > 1) {
+ if (ev->nesting.hook_fn) {
+ int ret2;
+ ret2 = ev->nesting.hook_fn(ev,
+ ev->nesting.hook_private,
+ ev->nesting.level,
+ false,
+ (void *)&nesting_stack_ptr,
+ location);
+ if (ret2 != 0) {
+ ret = ret2;
+ goto done;
+ }
+ }
+ }
+
+done:
+ ev->nesting.level--;
+ return ret;
+}
+
+/*
+ this is a performance optimization for the samba4 nested event loop problems
+*/
+int _tevent_loop_until(struct tevent_context *ev,
+ bool (*finished)(void *private_data),
+ void *private_data,
+ const char *location)
+{
+ int ret = 0;
+ void *nesting_stack_ptr = NULL;
+
+ ev->nesting.level++;
+
+ if (ev->nesting.level > 1) {
+ if (!ev->nesting.allowed) {
+ tevent_abort_nesting(ev, location);
+ errno = ELOOP;
+ return -1;
+ }
+ if (ev->nesting.hook_fn) {
+ int ret2;
+ ret2 = ev->nesting.hook_fn(ev,
+ ev->nesting.hook_private,
+ ev->nesting.level,
+ true,
+ (void *)&nesting_stack_ptr,
+ location);
+ if (ret2 != 0) {
+ ret = ret2;
+ goto done;
+ }
+ }
+ }
+
+ while (!finished(private_data)) {
+ ret = ev->ops->loop_once(ev, location);
+ if (ret != 0) {
+ break;
+ }
+ }
+
+ if (ev->nesting.level > 1) {
+ if (ev->nesting.hook_fn) {
+ int ret2;
+ ret2 = ev->nesting.hook_fn(ev,
+ ev->nesting.hook_private,
+ ev->nesting.level,
+ false,
+ (void *)&nesting_stack_ptr,
+ location);
+ if (ret2 != 0) {
+ ret = ret2;
+ goto done;
+ }
+ }
+ }
+
+done:
+ ev->nesting.level--;
+ return ret;
}
/*
return on failure or (with 0) if all fd events are removed
*/
-int tevent_loop_wait(struct tevent_context *ev)
+int _tevent_loop_wait(struct tevent_context *ev, const char *location)
{
- return ev->ops->loop_wait(ev);
+ return ev->ops->loop_wait(ev, location);
}