s3-events: make the old timed events compatible with tevent
[ira/wip.git] / source3 / lib / events.c
index 8c56941829002030cbb654beb1fcc7d030c1e37b..75aa250726699ca896fe1953c1a3df8ee1aef566 100644 (file)
@@ -70,6 +70,11 @@ bool event_add_to_select_args(struct tevent_context *ev,
                }
        }
 
+       if (ev->immediate_events != NULL) {
+               *timeout = timeval_zero();
+               return true;
+       }
+
        if (ev->timer_events == NULL) {
                return ret;
        }
@@ -91,16 +96,38 @@ bool run_events(struct tevent_context *ev,
                return true;
        }
 
+       if (ev->immediate_events &&
+           tevent_common_loop_immediate(ev)) {
+               return true;
+       }
+
        GetTimeOfDay(&now);
 
        if ((ev->timer_events != NULL)
            && (timeval_compare(&now, &ev->timer_events->next_event) >= 0)) {
+               /* this older events system did not auto-free timed
+                  events on running them, and had a race condition
+                  where the event could be called twice if the
+                  talloc_free of the te happened after the callback
+                  made a call which invoked the event loop. To avoid
+                  this while still allowing old code which frees the
+                  te, we need to create a temporary context which
+                  will be used to ensure the te is freed. We also
+                  remove the te from the timed event list before we
+                  call the handler, to ensure we can't loop */
+
+               struct tevent_timer *te = ev->timer_events;
+               TALLOC_CTX *tmp_ctx = talloc_new(ev);
 
                DEBUG(10, ("Running timed event \"%s\" %p\n",
                           ev->timer_events->handler_name, ev->timer_events));
 
-               ev->timer_events->handler(ev, ev->timer_events, now,
-                                         ev->timer_events->private_data);
+               DLIST_REMOVE(ev->timer_events, te);
+               talloc_steal(tmp_ctx, te);
+
+               te->handler(ev, te, now, te->private_data);
+
+               talloc_free(tmp_ctx);
                return true;
        }
 
@@ -132,9 +159,13 @@ struct timeval *get_timed_events_timeout(struct tevent_context *ev,
 {
        struct timeval now;
 
-       if (ev->timer_events == NULL) {
+       if ((ev->timer_events == NULL) && (ev->immediate_events == NULL)) {
                return NULL;
        }
+       if (ev->immediate_events != NULL) {
+               *to_ret = timeval_zero();
+               return to_ret;
+       }
 
        now = timeval_current();
        *to_ret = timeval_until(&now, &ev->timer_events->next_event);
@@ -181,17 +212,6 @@ static int s3_event_loop_once(struct tevent_context *ev, const char *location)
        return 0;
 }
 
-static int s3_event_loop_wait(struct tevent_context *ev, const char *location)
-{
-       int ret = 0;
-
-       while (ret == 0) {
-               ret = s3_event_loop_once(ev, location);
-       }
-
-       return ret;
-}
-
 void event_context_reinit(struct tevent_context *ev)
 {
        tevent_common_context_destructor(ev);
@@ -238,15 +258,16 @@ void dump_event_list(struct tevent_context *ev)
 }
 
 static const struct tevent_ops s3_event_ops = {
-       .context_init   = s3_event_context_init,
-       .add_fd         = tevent_common_add_fd,
-       .set_fd_close_fn= tevent_common_fd_set_close_fn,
-       .get_fd_flags   = tevent_common_fd_get_flags,
-       .set_fd_flags   = tevent_common_fd_set_flags,
-       .add_timer      = tevent_common_add_timer,
-       .add_signal     = tevent_common_add_signal,
-       .loop_once      = s3_event_loop_once,
-       .loop_wait      = s3_event_loop_wait,
+       .context_init           = s3_event_context_init,
+       .add_fd                 = tevent_common_add_fd,
+       .set_fd_close_fn        = tevent_common_fd_set_close_fn,
+       .get_fd_flags           = tevent_common_fd_get_flags,
+       .set_fd_flags           = tevent_common_fd_set_flags,
+       .add_timer              = tevent_common_add_timer,
+       .schedule_immediate     = tevent_common_schedule_immediate,
+       .add_signal             = tevent_common_add_signal,
+       .loop_once              = s3_event_loop_once,
+       .loop_wait              = tevent_common_loop_wait,
 };
 
 static bool s3_tevent_init(void)
@@ -282,7 +303,7 @@ static void s3_event_debug(void *context, enum tevent_debug_level level,
                samba_level = 2;
                break;
        case TEVENT_DEBUG_TRACE:
-               samba_level = 10;
+               samba_level = 11;
                break;
 
        };