summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/tevent/tevent.c62
-rw-r--r--lib/tevent/tevent.h6
2 files changed, 68 insertions, 0 deletions
diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c
index e9b6b7d055..a9e18c349d 100644
--- a/lib/tevent/tevent.c
+++ b/lib/tevent/tevent.c
@@ -450,6 +450,68 @@ done:
}
/*
+ 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;
+ 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, const char *location)
diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h
index bb36f39739..4a3f51ae5e 100644
--- a/lib/tevent/tevent.h
+++ b/lib/tevent/tevent.h
@@ -319,6 +319,12 @@ void tevent_loop_allow_nesting(struct tevent_context *ev) _DEPRECATED_;
void tevent_loop_set_nesting_hook(struct tevent_context *ev,
tevent_nesting_hook hook,
void *private_data) _DEPRECATED_;
+int _tevent_loop_until(struct tevent_context *ev,
+ bool (*finished)(void *private_data),
+ void *private_data,
+ const char *location) _DEPRECATED_;
+#define tevent_loop_until(ev, finished, private_data) \
+ _tevent_loop_until(ev, finished, private_data, __location__)
#endif
#ifdef TEVENT_COMPAT_DEFINES