diff options
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/events.c | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/source3/lib/events.c b/source3/lib/events.c index 7a06ad0829..75aa250726 100644 --- a/source3/lib/events.c +++ b/source3/lib/events.c @@ -105,12 +105,29 @@ bool run_events(struct tevent_context *ev, 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; } |